cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

via_clock.c (8805B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
      4 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
      5 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
      6 */
      7/*
      8 * clock and PLL management functions
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/via-core.h>
     13
     14#include "via_clock.h"
     15#include "global.h"
     16#include "debug.h"
     17
     18static const char *via_slap = "Please slap VIA Technologies to motivate them "
     19	"releasing full documentation for your platform!\n";
     20
     21static inline u32 cle266_encode_pll(struct via_pll_config pll)
     22{
     23	return (pll.multiplier << 8)
     24		| (pll.rshift << 6)
     25		| pll.divisor;
     26}
     27
     28static inline u32 k800_encode_pll(struct via_pll_config pll)
     29{
     30	return ((pll.divisor - 2) << 16)
     31		| (pll.rshift << 10)
     32		| (pll.multiplier - 2);
     33}
     34
     35static inline u32 vx855_encode_pll(struct via_pll_config pll)
     36{
     37	return (pll.divisor << 16)
     38		| (pll.rshift << 10)
     39		| pll.multiplier;
     40}
     41
     42static inline void cle266_set_primary_pll_encoded(u32 data)
     43{
     44	via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */
     45	via_write_reg(VIASR, 0x46, data & 0xFF);
     46	via_write_reg(VIASR, 0x47, (data >> 8) & 0xFF);
     47	via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */
     48}
     49
     50static inline void k800_set_primary_pll_encoded(u32 data)
     51{
     52	via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */
     53	via_write_reg(VIASR, 0x44, data & 0xFF);
     54	via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF);
     55	via_write_reg(VIASR, 0x46, (data >> 16) & 0xFF);
     56	via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */
     57}
     58
     59static inline void cle266_set_secondary_pll_encoded(u32 data)
     60{
     61	via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */
     62	via_write_reg(VIASR, 0x44, data & 0xFF);
     63	via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF);
     64	via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
     65}
     66
     67static inline void k800_set_secondary_pll_encoded(u32 data)
     68{
     69	via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */
     70	via_write_reg(VIASR, 0x4A, data & 0xFF);
     71	via_write_reg(VIASR, 0x4B, (data >> 8) & 0xFF);
     72	via_write_reg(VIASR, 0x4C, (data >> 16) & 0xFF);
     73	via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
     74}
     75
     76static inline void set_engine_pll_encoded(u32 data)
     77{
     78	via_write_reg_mask(VIASR, 0x40, 0x01, 0x01); /* enable reset */
     79	via_write_reg(VIASR, 0x47, data & 0xFF);
     80	via_write_reg(VIASR, 0x48, (data >> 8) & 0xFF);
     81	via_write_reg(VIASR, 0x49, (data >> 16) & 0xFF);
     82	via_write_reg_mask(VIASR, 0x40, 0x00, 0x01); /* disable reset */
     83}
     84
     85static void cle266_set_primary_pll(struct via_pll_config config)
     86{
     87	cle266_set_primary_pll_encoded(cle266_encode_pll(config));
     88}
     89
     90static void k800_set_primary_pll(struct via_pll_config config)
     91{
     92	k800_set_primary_pll_encoded(k800_encode_pll(config));
     93}
     94
     95static void vx855_set_primary_pll(struct via_pll_config config)
     96{
     97	k800_set_primary_pll_encoded(vx855_encode_pll(config));
     98}
     99
    100static void cle266_set_secondary_pll(struct via_pll_config config)
    101{
    102	cle266_set_secondary_pll_encoded(cle266_encode_pll(config));
    103}
    104
    105static void k800_set_secondary_pll(struct via_pll_config config)
    106{
    107	k800_set_secondary_pll_encoded(k800_encode_pll(config));
    108}
    109
    110static void vx855_set_secondary_pll(struct via_pll_config config)
    111{
    112	k800_set_secondary_pll_encoded(vx855_encode_pll(config));
    113}
    114
    115static void k800_set_engine_pll(struct via_pll_config config)
    116{
    117	set_engine_pll_encoded(k800_encode_pll(config));
    118}
    119
    120static void vx855_set_engine_pll(struct via_pll_config config)
    121{
    122	set_engine_pll_encoded(vx855_encode_pll(config));
    123}
    124
    125static void set_primary_pll_state(u8 state)
    126{
    127	u8 value;
    128
    129	switch (state) {
    130	case VIA_STATE_ON:
    131		value = 0x20;
    132		break;
    133	case VIA_STATE_OFF:
    134		value = 0x00;
    135		break;
    136	default:
    137		return;
    138	}
    139
    140	via_write_reg_mask(VIASR, 0x2D, value, 0x30);
    141}
    142
    143static void set_secondary_pll_state(u8 state)
    144{
    145	u8 value;
    146
    147	switch (state) {
    148	case VIA_STATE_ON:
    149		value = 0x08;
    150		break;
    151	case VIA_STATE_OFF:
    152		value = 0x00;
    153		break;
    154	default:
    155		return;
    156	}
    157
    158	via_write_reg_mask(VIASR, 0x2D, value, 0x0C);
    159}
    160
    161static void set_engine_pll_state(u8 state)
    162{
    163	u8 value;
    164
    165	switch (state) {
    166	case VIA_STATE_ON:
    167		value = 0x02;
    168		break;
    169	case VIA_STATE_OFF:
    170		value = 0x00;
    171		break;
    172	default:
    173		return;
    174	}
    175
    176	via_write_reg_mask(VIASR, 0x2D, value, 0x03);
    177}
    178
    179static void set_primary_clock_state(u8 state)
    180{
    181	u8 value;
    182
    183	switch (state) {
    184	case VIA_STATE_ON:
    185		value = 0x20;
    186		break;
    187	case VIA_STATE_OFF:
    188		value = 0x00;
    189		break;
    190	default:
    191		return;
    192	}
    193
    194	via_write_reg_mask(VIASR, 0x1B, value, 0x30);
    195}
    196
    197static void set_secondary_clock_state(u8 state)
    198{
    199	u8 value;
    200
    201	switch (state) {
    202	case VIA_STATE_ON:
    203		value = 0x80;
    204		break;
    205	case VIA_STATE_OFF:
    206		value = 0x00;
    207		break;
    208	default:
    209		return;
    210	}
    211
    212	via_write_reg_mask(VIASR, 0x1B, value, 0xC0);
    213}
    214
    215static inline u8 set_clock_source_common(enum via_clksrc source, bool use_pll)
    216{
    217	u8 data = 0;
    218
    219	switch (source) {
    220	case VIA_CLKSRC_X1:
    221		data = 0x00;
    222		break;
    223	case VIA_CLKSRC_TVX1:
    224		data = 0x02;
    225		break;
    226	case VIA_CLKSRC_TVPLL:
    227		data = 0x04; /* 0x06 should be the same */
    228		break;
    229	case VIA_CLKSRC_DVP1TVCLKR:
    230		data = 0x0A;
    231		break;
    232	case VIA_CLKSRC_CAP0:
    233		data = 0xC;
    234		break;
    235	case VIA_CLKSRC_CAP1:
    236		data = 0x0E;
    237		break;
    238	}
    239
    240	if (!use_pll)
    241		data |= 1;
    242
    243	return data;
    244}
    245
    246static void set_primary_clock_source(enum via_clksrc source, bool use_pll)
    247{
    248	u8 data = set_clock_source_common(source, use_pll) << 4;
    249	via_write_reg_mask(VIACR, 0x6C, data, 0xF0);
    250}
    251
    252static void set_secondary_clock_source(enum via_clksrc source, bool use_pll)
    253{
    254	u8 data = set_clock_source_common(source, use_pll);
    255	via_write_reg_mask(VIACR, 0x6C, data, 0x0F);
    256}
    257
    258static void dummy_set_clock_state(u8 state)
    259{
    260	printk(KERN_INFO "Using undocumented set clock state.\n%s", via_slap);
    261}
    262
    263static void dummy_set_clock_source(enum via_clksrc source, bool use_pll)
    264{
    265	printk(KERN_INFO "Using undocumented set clock source.\n%s", via_slap);
    266}
    267
    268static void dummy_set_pll_state(u8 state)
    269{
    270	printk(KERN_INFO "Using undocumented set PLL state.\n%s", via_slap);
    271}
    272
    273static void dummy_set_pll(struct via_pll_config config)
    274{
    275	printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
    276}
    277
    278static void noop_set_clock_state(u8 state)
    279{
    280}
    281
    282void via_clock_init(struct via_clock *clock, int gfx_chip)
    283{
    284	switch (gfx_chip) {
    285	case UNICHROME_CLE266:
    286	case UNICHROME_K400:
    287		clock->set_primary_clock_state = dummy_set_clock_state;
    288		clock->set_primary_clock_source = dummy_set_clock_source;
    289		clock->set_primary_pll_state = dummy_set_pll_state;
    290		clock->set_primary_pll = cle266_set_primary_pll;
    291
    292		clock->set_secondary_clock_state = dummy_set_clock_state;
    293		clock->set_secondary_clock_source = dummy_set_clock_source;
    294		clock->set_secondary_pll_state = dummy_set_pll_state;
    295		clock->set_secondary_pll = cle266_set_secondary_pll;
    296
    297		clock->set_engine_pll_state = dummy_set_pll_state;
    298		clock->set_engine_pll = dummy_set_pll;
    299		break;
    300	case UNICHROME_K800:
    301	case UNICHROME_PM800:
    302	case UNICHROME_CN700:
    303	case UNICHROME_CX700:
    304	case UNICHROME_CN750:
    305	case UNICHROME_K8M890:
    306	case UNICHROME_P4M890:
    307	case UNICHROME_P4M900:
    308	case UNICHROME_VX800:
    309		clock->set_primary_clock_state = set_primary_clock_state;
    310		clock->set_primary_clock_source = set_primary_clock_source;
    311		clock->set_primary_pll_state = set_primary_pll_state;
    312		clock->set_primary_pll = k800_set_primary_pll;
    313
    314		clock->set_secondary_clock_state = set_secondary_clock_state;
    315		clock->set_secondary_clock_source = set_secondary_clock_source;
    316		clock->set_secondary_pll_state = set_secondary_pll_state;
    317		clock->set_secondary_pll = k800_set_secondary_pll;
    318
    319		clock->set_engine_pll_state = set_engine_pll_state;
    320		clock->set_engine_pll = k800_set_engine_pll;
    321		break;
    322	case UNICHROME_VX855:
    323	case UNICHROME_VX900:
    324		clock->set_primary_clock_state = set_primary_clock_state;
    325		clock->set_primary_clock_source = set_primary_clock_source;
    326		clock->set_primary_pll_state = set_primary_pll_state;
    327		clock->set_primary_pll = vx855_set_primary_pll;
    328
    329		clock->set_secondary_clock_state = set_secondary_clock_state;
    330		clock->set_secondary_clock_source = set_secondary_clock_source;
    331		clock->set_secondary_pll_state = set_secondary_pll_state;
    332		clock->set_secondary_pll = vx855_set_secondary_pll;
    333
    334		clock->set_engine_pll_state = set_engine_pll_state;
    335		clock->set_engine_pll = vx855_set_engine_pll;
    336		break;
    337
    338	}
    339
    340	if (machine_is_olpc()) {
    341		/* The OLPC XO-1.5 cannot suspend/resume reliably if the
    342		 * IGA1/IGA2 clocks are set as on or off (memory rot
    343		 * occasionally happens during suspend under such
    344		 * configurations).
    345		 *
    346		 * The only known stable scenario is to leave this bits as-is,
    347		 * which in their default states are documented to enable the
    348		 * clock only when it is needed.
    349		 */
    350		clock->set_primary_clock_state = noop_set_clock_state;
    351		clock->set_secondary_clock_state = noop_set_clock_state;
    352	}
    353}