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

at91sam9x5.c (8711B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/clk-provider.h>
      3#include <linux/mfd/syscon.h>
      4#include <linux/slab.h>
      5
      6#include <dt-bindings/clock/at91.h>
      7
      8#include "pmc.h"
      9
     10static DEFINE_SPINLOCK(mck_lock);
     11
     12static const struct clk_master_characteristics mck_characteristics = {
     13	.output = { .min = 0, .max = 133333333 },
     14	.divisors = { 1, 2, 4, 3 },
     15	.have_div3_pres = 1,
     16};
     17
     18static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
     19
     20static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
     21
     22static const struct clk_range plla_outputs[] = {
     23	{ .min = 745000000, .max = 800000000 },
     24	{ .min = 695000000, .max = 750000000 },
     25	{ .min = 645000000, .max = 700000000 },
     26	{ .min = 595000000, .max = 650000000 },
     27	{ .min = 545000000, .max = 600000000 },
     28	{ .min = 495000000, .max = 555000000 },
     29	{ .min = 445000000, .max = 500000000 },
     30	{ .min = 400000000, .max = 450000000 },
     31};
     32
     33static const struct clk_pll_characteristics plla_characteristics = {
     34	.input = { .min = 2000000, .max = 32000000 },
     35	.num_output = ARRAY_SIZE(plla_outputs),
     36	.output = plla_outputs,
     37	.icpll = plla_icpll,
     38	.out = plla_out,
     39};
     40
     41static const struct {
     42	char *n;
     43	char *p;
     44	u8 id;
     45} at91sam9x5_systemck[] = {
     46	{ .n = "ddrck", .p = "masterck_div", .id = 2 },
     47	{ .n = "smdck", .p = "smdclk",   .id = 4 },
     48	{ .n = "uhpck", .p = "usbck",    .id = 6 },
     49	{ .n = "udpck", .p = "usbck",    .id = 7 },
     50	{ .n = "pck0",  .p = "prog0",    .id = 8 },
     51	{ .n = "pck1",  .p = "prog1",    .id = 9 },
     52};
     53
     54static const struct clk_pcr_layout at91sam9x5_pcr_layout = {
     55	.offset = 0x10c,
     56	.cmd = BIT(12),
     57	.pid_mask = GENMASK(5, 0),
     58	.div_mask = GENMASK(17, 16),
     59};
     60
     61struct pck {
     62	char *n;
     63	u8 id;
     64};
     65
     66static const struct pck at91sam9x5_periphck[] = {
     67	{ .n = "pioAB_clk",  .id = 2, },
     68	{ .n = "pioCD_clk",  .id = 3, },
     69	{ .n = "smd_clk",    .id = 4, },
     70	{ .n = "usart0_clk", .id = 5, },
     71	{ .n = "usart1_clk", .id = 6, },
     72	{ .n = "usart2_clk", .id = 7, },
     73	{ .n = "twi0_clk",   .id = 9, },
     74	{ .n = "twi1_clk",   .id = 10, },
     75	{ .n = "twi2_clk",   .id = 11, },
     76	{ .n = "mci0_clk",   .id = 12, },
     77	{ .n = "spi0_clk",   .id = 13, },
     78	{ .n = "spi1_clk",   .id = 14, },
     79	{ .n = "uart0_clk",  .id = 15, },
     80	{ .n = "uart1_clk",  .id = 16, },
     81	{ .n = "tcb0_clk",   .id = 17, },
     82	{ .n = "pwm_clk",    .id = 18, },
     83	{ .n = "adc_clk",    .id = 19, },
     84	{ .n = "dma0_clk",   .id = 20, },
     85	{ .n = "dma1_clk",   .id = 21, },
     86	{ .n = "uhphs_clk",  .id = 22, },
     87	{ .n = "udphs_clk",  .id = 23, },
     88	{ .n = "mci1_clk",   .id = 26, },
     89	{ .n = "ssc0_clk",   .id = 28, },
     90};
     91
     92static const struct pck at91sam9g15_periphck[] = {
     93	{ .n = "lcdc_clk", .id = 25, },
     94	{ /* sentinel */}
     95};
     96
     97static const struct pck at91sam9g25_periphck[] = {
     98	{ .n = "usart3_clk", .id = 8, },
     99	{ .n = "macb0_clk", .id = 24, },
    100	{ .n = "isi_clk", .id = 25, },
    101	{ /* sentinel */}
    102};
    103
    104static const struct pck at91sam9g35_periphck[] = {
    105	{ .n = "macb0_clk", .id = 24, },
    106	{ .n = "lcdc_clk", .id = 25, },
    107	{ /* sentinel */}
    108};
    109
    110static const struct pck at91sam9x25_periphck[] = {
    111	{ .n = "usart3_clk", .id = 8, },
    112	{ .n = "macb0_clk", .id = 24, },
    113	{ .n = "macb1_clk", .id = 27, },
    114	{ .n = "can0_clk", .id = 29, },
    115	{ .n = "can1_clk", .id = 30, },
    116	{ /* sentinel */}
    117};
    118
    119static const struct pck at91sam9x35_periphck[] = {
    120	{ .n = "macb0_clk", .id = 24, },
    121	{ .n = "lcdc_clk", .id = 25, },
    122	{ .n = "can0_clk", .id = 29, },
    123	{ .n = "can1_clk", .id = 30, },
    124	{ /* sentinel */}
    125};
    126
    127static void __init at91sam9x5_pmc_setup(struct device_node *np,
    128					const struct pck *extra_pcks,
    129					bool has_lcdck)
    130{
    131	struct clk_range range = CLK_RANGE(0, 0);
    132	const char *slck_name, *mainxtal_name;
    133	struct pmc_data *at91sam9x5_pmc;
    134	const char *parent_names[6];
    135	struct regmap *regmap;
    136	struct clk_hw *hw;
    137	int i;
    138	bool bypass;
    139
    140	i = of_property_match_string(np, "clock-names", "slow_clk");
    141	if (i < 0)
    142		return;
    143
    144	slck_name = of_clk_get_parent_name(np, i);
    145
    146	i = of_property_match_string(np, "clock-names", "main_xtal");
    147	if (i < 0)
    148		return;
    149	mainxtal_name = of_clk_get_parent_name(np, i);
    150
    151	regmap = device_node_to_regmap(np);
    152	if (IS_ERR(regmap))
    153		return;
    154
    155	at91sam9x5_pmc = pmc_data_allocate(PMC_PLLACK + 1,
    156					   nck(at91sam9x5_systemck), 31, 0, 2);
    157	if (!at91sam9x5_pmc)
    158		return;
    159
    160	hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
    161					   50000000);
    162	if (IS_ERR(hw))
    163		goto err_free;
    164
    165	bypass = of_property_read_bool(np, "atmel,osc-bypass");
    166
    167	hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
    168					bypass);
    169	if (IS_ERR(hw))
    170		goto err_free;
    171
    172	parent_names[0] = "main_rc_osc";
    173	parent_names[1] = "main_osc";
    174	hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
    175	if (IS_ERR(hw))
    176		goto err_free;
    177
    178	at91sam9x5_pmc->chws[PMC_MAIN] = hw;
    179
    180	hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
    181				   &at91rm9200_pll_layout, &plla_characteristics);
    182	if (IS_ERR(hw))
    183		goto err_free;
    184
    185	hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
    186	if (IS_ERR(hw))
    187		goto err_free;
    188
    189	at91sam9x5_pmc->chws[PMC_PLLACK] = hw;
    190
    191	hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
    192	if (IS_ERR(hw))
    193		goto err_free;
    194
    195	at91sam9x5_pmc->chws[PMC_UTMI] = hw;
    196
    197	parent_names[0] = slck_name;
    198	parent_names[1] = "mainck";
    199	parent_names[2] = "plladivck";
    200	parent_names[3] = "utmick";
    201	hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
    202					   parent_names,
    203					   &at91sam9x5_master_layout,
    204					   &mck_characteristics, &mck_lock);
    205	if (IS_ERR(hw))
    206		goto err_free;
    207
    208	hw = at91_clk_register_master_div(regmap, "masterck_div",
    209					  "masterck_pres",
    210					  &at91sam9x5_master_layout,
    211					  &mck_characteristics, &mck_lock,
    212					  CLK_SET_RATE_GATE, 0);
    213	if (IS_ERR(hw))
    214		goto err_free;
    215
    216	at91sam9x5_pmc->chws[PMC_MCK] = hw;
    217
    218	parent_names[0] = "plladivck";
    219	parent_names[1] = "utmick";
    220	hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
    221	if (IS_ERR(hw))
    222		goto err_free;
    223
    224	hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2);
    225	if (IS_ERR(hw))
    226		goto err_free;
    227
    228	parent_names[0] = slck_name;
    229	parent_names[1] = "mainck";
    230	parent_names[2] = "plladivck";
    231	parent_names[3] = "utmick";
    232	parent_names[4] = "masterck_div";
    233	for (i = 0; i < 2; i++) {
    234		char name[6];
    235
    236		snprintf(name, sizeof(name), "prog%d", i);
    237
    238		hw = at91_clk_register_programmable(regmap, name,
    239						    parent_names, 5, i,
    240						    &at91sam9x5_programmable_layout,
    241						    NULL);
    242		if (IS_ERR(hw))
    243			goto err_free;
    244
    245		at91sam9x5_pmc->pchws[i] = hw;
    246	}
    247
    248	for (i = 0; i < ARRAY_SIZE(at91sam9x5_systemck); i++) {
    249		hw = at91_clk_register_system(regmap, at91sam9x5_systemck[i].n,
    250					      at91sam9x5_systemck[i].p,
    251					      at91sam9x5_systemck[i].id);
    252		if (IS_ERR(hw))
    253			goto err_free;
    254
    255		at91sam9x5_pmc->shws[at91sam9x5_systemck[i].id] = hw;
    256	}
    257
    258	if (has_lcdck) {
    259		hw = at91_clk_register_system(regmap, "lcdck", "masterck_div", 3);
    260		if (IS_ERR(hw))
    261			goto err_free;
    262
    263		at91sam9x5_pmc->shws[3] = hw;
    264	}
    265
    266	for (i = 0; i < ARRAY_SIZE(at91sam9x5_periphck); i++) {
    267		hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
    268							 &at91sam9x5_pcr_layout,
    269							 at91sam9x5_periphck[i].n,
    270							 "masterck_div",
    271							 at91sam9x5_periphck[i].id,
    272							 &range, INT_MIN);
    273		if (IS_ERR(hw))
    274			goto err_free;
    275
    276		at91sam9x5_pmc->phws[at91sam9x5_periphck[i].id] = hw;
    277	}
    278
    279	for (i = 0; extra_pcks[i].id; i++) {
    280		hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
    281							 &at91sam9x5_pcr_layout,
    282							 extra_pcks[i].n,
    283							 "masterck_div",
    284							 extra_pcks[i].id,
    285							 &range, INT_MIN);
    286		if (IS_ERR(hw))
    287			goto err_free;
    288
    289		at91sam9x5_pmc->phws[extra_pcks[i].id] = hw;
    290	}
    291
    292	of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9x5_pmc);
    293
    294	return;
    295
    296err_free:
    297	kfree(at91sam9x5_pmc);
    298}
    299
    300static void __init at91sam9g15_pmc_setup(struct device_node *np)
    301{
    302	at91sam9x5_pmc_setup(np, at91sam9g15_periphck, true);
    303}
    304
    305CLK_OF_DECLARE(at91sam9g15_pmc, "atmel,at91sam9g15-pmc", at91sam9g15_pmc_setup);
    306
    307static void __init at91sam9g25_pmc_setup(struct device_node *np)
    308{
    309	at91sam9x5_pmc_setup(np, at91sam9g25_periphck, false);
    310}
    311
    312CLK_OF_DECLARE(at91sam9g25_pmc, "atmel,at91sam9g25-pmc", at91sam9g25_pmc_setup);
    313
    314static void __init at91sam9g35_pmc_setup(struct device_node *np)
    315{
    316	at91sam9x5_pmc_setup(np, at91sam9g35_periphck, true);
    317}
    318
    319CLK_OF_DECLARE(at91sam9g35_pmc, "atmel,at91sam9g35-pmc", at91sam9g35_pmc_setup);
    320
    321static void __init at91sam9x25_pmc_setup(struct device_node *np)
    322{
    323	at91sam9x5_pmc_setup(np, at91sam9x25_periphck, false);
    324}
    325
    326CLK_OF_DECLARE(at91sam9x25_pmc, "atmel,at91sam9x25-pmc", at91sam9x25_pmc_setup);
    327
    328static void __init at91sam9x35_pmc_setup(struct device_node *np)
    329{
    330	at91sam9x5_pmc_setup(np, at91sam9x35_periphck, true);
    331}
    332
    333CLK_OF_DECLARE(at91sam9x35_pmc, "atmel,at91sam9x35-pmc", at91sam9x35_pmc_setup);