1/* 2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6#include <stdlib.h> 7#include <string.h> 8 9#include <sel4vm/guest_vm.h> 10#include <sel4vmmplatsupport/device.h> 11#include <sel4vmmplatsupport/arch/ac_device.h> 12#include <sel4vmmplatsupport/plat/device_map.h> 13#include <sel4vmmplatsupport/plat/vclock.h> 14 15#define CLOCK_REG_DEFN(r, o, s, b) { .bank = CLKREGS_##r, .offset = o, .shift = s, .bits = b } 16#define CLK_DEFN(c) { .nregs = sizeof(c)/sizeof(*c), .regs = &c[0] } 17#define CLK_DEFN_NONE() { .nregs = 0, .regs = NULL } 18 19struct clock_reg { 20 int bank; 21 int offset; 22 int shift; 23 int bits; 24}; 25 26struct clock_data { 27 int nregs; 28 struct clock_reg *regs; 29}; 30 31struct clock_reg sclkmpll_data[] = { 32 CLOCK_REG_DEFN(CORE, 0x000, 0, 32), /* LOCK */ 33 CLOCK_REG_DEFN(CORE, 0x100, 0, 32), /* CON0 */ 34 CLOCK_REG_DEFN(CORE, 0x104, 0, 32), /* CON1 */ 35}; 36struct clock_reg sclkbpll_data[] = { 37 CLOCK_REG_DEFN(CDREX, 0x010, 0, 32), /* LOCK */ 38 CLOCK_REG_DEFN(CDREX, 0x110, 0, 32), /* CON0 */ 39 CLOCK_REG_DEFN(CDREX, 0x114, 0, 32), /* CON1 */ 40}; 41struct clock_reg sclkcpll_data[] = { 42 CLOCK_REG_DEFN(TOP, 0x020, 0, 32), /* LOCK */ 43 CLOCK_REG_DEFN(TOP, 0x120, 0, 32), /* CON0 */ 44 CLOCK_REG_DEFN(TOP, 0x124, 0, 32), /* CON1 */ 45 CLOCK_REG_DEFN(TOP, 0x128, 0, 32), /* CON2 */ 46}; 47struct clock_reg sclkgpll_data[] = { 48 CLOCK_REG_DEFN(TOP, 0x050, 0, 32), /* LOCK */ 49 CLOCK_REG_DEFN(TOP, 0x150, 0, 32), /* CON0 */ 50 CLOCK_REG_DEFN(TOP, 0x154, 0, 32), /* CON1 */ 51}; 52struct clock_reg sclkepll_data[] = { 53 CLOCK_REG_DEFN(TOP, 0x030, 0, 32), /* LOCK */ 54 CLOCK_REG_DEFN(TOP, 0x130, 0, 32), /* CON0 */ 55 CLOCK_REG_DEFN(TOP, 0x134, 0, 32), /* CON1 */ 56 CLOCK_REG_DEFN(TOP, 0x138, 0, 32), /* CON2 */ 57}; 58struct clock_reg sclkvpll_data[] = { 59 CLOCK_REG_DEFN(TOP, 0x040, 0, 32), /* LOCK */ 60 CLOCK_REG_DEFN(TOP, 0x140, 0, 32), /* CON0 */ 61 CLOCK_REG_DEFN(TOP, 0x144, 0, 32), /* CON1 */ 62 CLOCK_REG_DEFN(TOP, 0x148, 0, 32), /* CON2 */ 63}; 64 65struct clock_reg uart0_data[] = { 66 CLOCK_REG_DEFN(TOP, 0x250, 0, 4), /* SEL */ 67 CLOCK_REG_DEFN(TOP, 0x350, 0, 1), /* MASK */ 68 CLOCK_REG_DEFN(TOP, 0x558, 0, 4), /* DIV */ 69 CLOCK_REG_DEFN(TOP, 0x658, 0, 1), /* DIVSTAT */ 70 CLOCK_REG_DEFN(TOP, 0x950, 0, 1), /* GATE */ 71}; 72struct clock_reg uart1_data[] = { 73 CLOCK_REG_DEFN(TOP, 0x250, 4, 4), /* SEL */ 74 CLOCK_REG_DEFN(TOP, 0x350, 4, 1), /* MASK */ 75 CLOCK_REG_DEFN(TOP, 0x558, 4, 4), /* DIV */ 76 CLOCK_REG_DEFN(TOP, 0x658, 4, 1), /* DIVSTAT */ 77 CLOCK_REG_DEFN(TOP, 0x950, 1, 1), /* GATE */ 78}; 79struct clock_reg uart2_data[] = { 80 CLOCK_REG_DEFN(TOP, 0x250, 8, 4), /* SEL */ 81 CLOCK_REG_DEFN(TOP, 0x350, 8, 1), /* MASK */ 82 CLOCK_REG_DEFN(TOP, 0x558, 8, 4), /* DIV */ 83 CLOCK_REG_DEFN(TOP, 0x658, 8, 1), /* DIVSTAT */ 84 CLOCK_REG_DEFN(TOP, 0x950, 2, 1), /* GATE */ 85}; 86struct clock_reg uart3_data[] = { 87 CLOCK_REG_DEFN(TOP, 0x250, 12, 4), /* SEL */ 88 CLOCK_REG_DEFN(TOP, 0x350, 12, 1), /* MASK */ 89 CLOCK_REG_DEFN(TOP, 0x558, 12, 4), /* DIV */ 90 CLOCK_REG_DEFN(TOP, 0x658, 12, 1), /* DIVSTAT */ 91 CLOCK_REG_DEFN(TOP, 0x950, 3, 1), /* GATE */ 92}; 93 94struct clock_reg spi0_data[] = { 95 CLOCK_REG_DEFN(TOP, 0x254, 16, 4), /* SEL */ 96 CLOCK_REG_DEFN(TOP, 0x354, 16, 1), /* MASK */ 97 CLOCK_REG_DEFN(TOP, 0x55C, 0, 4), /* DIV */ 98 CLOCK_REG_DEFN(TOP, 0x55C, 8, 8), /* DIV_PRE */ 99 CLOCK_REG_DEFN(TOP, 0x65C, 0, 1), /* DIVSTAT */ 100 CLOCK_REG_DEFN(TOP, 0x65C, 8, 1), /* DIVSTAT_PRE */ 101 CLOCK_REG_DEFN(TOP, 0x950, 16, 1), /* GATE */ 102}; 103struct clock_reg spi1_data[] = { 104 CLOCK_REG_DEFN(TOP, 0x254, 20, 4), /* SEL */ 105 CLOCK_REG_DEFN(TOP, 0x354, 20, 1), /* MASK */ 106 CLOCK_REG_DEFN(TOP, 0x55C, 16, 4), /* DIV */ 107 CLOCK_REG_DEFN(TOP, 0x55C, 24, 8), /* DIV_PRE */ 108 CLOCK_REG_DEFN(TOP, 0x65C, 16, 1), /* DIVSTAT */ 109 CLOCK_REG_DEFN(TOP, 0x65C, 24, 1), /* DIVSTAT_PRE */ 110 CLOCK_REG_DEFN(TOP, 0x950, 17, 1), /* GATE */ 111}; 112struct clock_reg spi2_data[] = { 113 CLOCK_REG_DEFN(TOP, 0x254, 24, 4), /* SEL */ 114 CLOCK_REG_DEFN(TOP, 0x354, 24, 1), /* MASK */ 115 CLOCK_REG_DEFN(TOP, 0x560, 0, 4), /* DIV */ 116 CLOCK_REG_DEFN(TOP, 0x560, 8, 8), /* DIV_PRE */ 117 CLOCK_REG_DEFN(TOP, 0x660, 0, 1), /* DIVSTAT */ 118 CLOCK_REG_DEFN(TOP, 0x660, 8, 1), /* DIVSTAT_PRE */ 119 CLOCK_REG_DEFN(TOP, 0x950, 18, 1), /* GATE */ 120}; 121 122struct clock_reg i2c0_data[] = { 123 CLOCK_REG_DEFN(TOP, 0x950, 6, 1), /* GATE */ 124}; 125struct clock_reg i2c1_data[] = { 126 CLOCK_REG_DEFN(TOP, 0x950, 7, 1), /* GATE */ 127}; 128struct clock_reg i2c2_data[] = { 129 CLOCK_REG_DEFN(TOP, 0x950, 8, 1), /* GATE */ 130}; 131struct clock_reg i2c3_data[] = { 132 CLOCK_REG_DEFN(TOP, 0x950, 9, 1), /* GATE */ 133}; 134struct clock_reg i2c4_data[] = { 135 CLOCK_REG_DEFN(TOP, 0x950, 10, 1), /* GATE */ 136}; 137struct clock_reg i2c5_data[] = { 138 CLOCK_REG_DEFN(TOP, 0x950, 11, 1), /* GATE */ 139}; 140struct clock_reg i2c6_data[] = { 141 CLOCK_REG_DEFN(TOP, 0x950, 12, 1), /* GATE */ 142}; 143struct clock_reg i2c7_data[] = { 144 CLOCK_REG_DEFN(TOP, 0x950, 13, 1), /* GATE */ 145}; 146 147struct clock_reg mmc0_data[] = { 148 CLOCK_REG_DEFN(TOP, 0x244, 0, 4), /* SEL */ 149 CLOCK_REG_DEFN(TOP, 0x340, 0, 1), /* MASK */ 150 CLOCK_REG_DEFN(TOP, 0x54C, 0, 4), /* DIV */ 151 CLOCK_REG_DEFN(TOP, 0x54C, 8, 8), /* DIV_PRE */ 152 CLOCK_REG_DEFN(TOP, 0x64C, 0, 1), /* DIVSTAT */ 153 CLOCK_REG_DEFN(TOP, 0x64C, 8, 1), /* DIVSTAT_PRE */ 154 CLOCK_REG_DEFN(TOP, 0x944, 12, 1), /* GATE */ 155}; 156struct clock_reg mmc1_data[] = { 157 CLOCK_REG_DEFN(TOP, 0x244, 4, 4), /* SEL */ 158 CLOCK_REG_DEFN(TOP, 0x340, 4, 1), /* MASK */ 159 CLOCK_REG_DEFN(TOP, 0x54C, 16, 4), /* DIV */ 160 CLOCK_REG_DEFN(TOP, 0x54C, 24, 8), /* DIV_PRE */ 161 CLOCK_REG_DEFN(TOP, 0x64C, 16, 1), /* DIVSTAT */ 162 CLOCK_REG_DEFN(TOP, 0x64C, 24, 1), /* DIVSTAT_PRE */ 163 CLOCK_REG_DEFN(TOP, 0x944, 13, 1), /* GATE */ 164}; 165struct clock_reg mmc2_data[] = { 166 CLOCK_REG_DEFN(TOP, 0x244, 8, 4), /* SEL */ 167 CLOCK_REG_DEFN(TOP, 0x340, 8, 1), /* MASK */ 168 CLOCK_REG_DEFN(TOP, 0x550, 0, 4), /* DIV */ 169 CLOCK_REG_DEFN(TOP, 0x550, 8, 8), /* DIV_PRE */ 170 CLOCK_REG_DEFN(TOP, 0x650, 0, 1), /* DIVSTAT */ 171 CLOCK_REG_DEFN(TOP, 0x650, 8, 1), /* DIVSTAT_PRE */ 172 CLOCK_REG_DEFN(TOP, 0x944, 14, 1), /* GATE */ 173}; 174struct clock_reg mmc3_data[] = { 175 CLOCK_REG_DEFN(TOP, 0x244, 12, 4), /* SEL */ 176 CLOCK_REG_DEFN(TOP, 0x340, 12, 1), /* MASK */ 177 CLOCK_REG_DEFN(TOP, 0x550, 16, 4), /* DIV */ 178 CLOCK_REG_DEFN(TOP, 0x550, 24, 8), /* DIV_PRE */ 179 CLOCK_REG_DEFN(TOP, 0x650, 16, 1), /* DIVSTAT */ 180 CLOCK_REG_DEFN(TOP, 0x650, 24, 1), /* DIVSTAT_PRE */ 181 CLOCK_REG_DEFN(TOP, 0x944, 15, 1), /* GATE */ 182}; 183 184struct clock_data clock_data[] = { 185 [CLK_MASTER ] = CLK_DEFN_NONE(), 186 [CLK_SCLKMPLL] = CLK_DEFN(sclkmpll_data), 187 [CLK_SCLKBPLL] = CLK_DEFN(sclkbpll_data), 188 [CLK_SCLKCPLL] = CLK_DEFN(sclkcpll_data), 189 [CLK_SCLKGPLL] = CLK_DEFN(sclkgpll_data), 190 [CLK_SCLKEPLL] = CLK_DEFN(sclkepll_data), 191 [CLK_SCLKVPLL] = CLK_DEFN(sclkvpll_data), 192 [CLK_SPI0 ] = CLK_DEFN(spi0_data), 193 [CLK_SPI1 ] = CLK_DEFN(spi1_data), 194 [CLK_SPI2 ] = CLK_DEFN(spi2_data), 195 [CLK_SPI0_ISP] = CLK_DEFN_NONE(), 196 [CLK_SPI1_ISP] = CLK_DEFN_NONE(), 197 [CLK_UART0 ] = CLK_DEFN(uart0_data), 198 [CLK_UART1 ] = CLK_DEFN(uart1_data), 199 [CLK_UART2 ] = CLK_DEFN(uart2_data), 200 [CLK_UART3 ] = CLK_DEFN(uart3_data), 201 [CLK_PWM ] = CLK_DEFN_NONE(), 202 [CLK_I2C0 ] = CLK_DEFN(i2c0_data), 203 [CLK_I2C1 ] = CLK_DEFN(i2c1_data), 204 [CLK_I2C2 ] = CLK_DEFN(i2c2_data), 205 [CLK_I2C3 ] = CLK_DEFN(i2c3_data), 206 [CLK_I2C4 ] = CLK_DEFN(i2c4_data), 207 [CLK_I2C5 ] = CLK_DEFN(i2c5_data), 208 [CLK_I2C6 ] = CLK_DEFN(i2c6_data), 209 [CLK_I2C7 ] = CLK_DEFN(i2c7_data), 210 [CLK_MMC0 ] = CLK_DEFN(mmc0_data), 211 [CLK_MMC1 ] = CLK_DEFN(mmc1_data), 212 [CLK_MMC2 ] = CLK_DEFN(mmc2_data), 213 [CLK_MMC3 ] = CLK_DEFN(mmc3_data) 214}; 215 216const struct device dev_cmu_cpu = { 217 .name = "CMU_CPU", 218 .pstart = CMU_CPU_PADDR, 219 .size = 0x1000, 220 .handle_device_fault = NULL, 221 .priv = NULL 222}; 223 224const struct device dev_cmu_core = { 225 .name = "CMU_CORE", 226 .pstart = CMU_CORE_PADDR, 227 .size = 0x1000, 228 .handle_device_fault = NULL, 229 .priv = NULL 230}; 231 232const struct device dev_cmu_acp = { 233 .name = "CMU_ACP", 234 .pstart = CMU_ACP_PADDR, 235 .size = 0x1000, 236 .handle_device_fault = NULL, 237 .priv = NULL 238}; 239 240const struct device dev_cmu_isp = { 241 .name = "CMU_ISP", 242 .pstart = CMU_ISP_PADDR, 243 .size = 0x1000, 244 .handle_device_fault = NULL, 245 .priv = NULL 246}; 247 248const struct device dev_cmu_top = { 249 .name = "CMU_TOP", 250 .pstart = CMU_TOP_PADDR, 251 .size = 0x1000, 252 .handle_device_fault = NULL, 253 .priv = NULL 254}; 255 256const struct device dev_cmu_cdrex = { 257 .name = "CMU_CDREX", 258 .pstart = CMU_CDREX_PADDR, 259 .size = 0x1000, 260 .handle_device_fault = NULL, 261 .priv = NULL 262}; 263 264const struct device dev_cmu_mem = { 265 .name = "CMU_MEM", 266 .pstart = CMU_MEM_PADDR, 267 .size = 0x1000, 268 .handle_device_fault = NULL, 269 .priv = NULL 270}; 271 272static const struct device *clock_devices[] = { 273 [CLKREGS_CPU ] = &dev_cmu_cpu, 274 [CLKREGS_CORE ] = &dev_cmu_core, 275 [CLKREGS_ACP ] = &dev_cmu_acp, 276 [CLKREGS_ISP ] = &dev_cmu_isp, 277 [CLKREGS_TOP ] = &dev_cmu_top, 278 [CLKREGS_LEX ] = NULL, 279 [CLKREGS_R0X ] = NULL, 280 [CLKREGS_R1X ] = NULL, 281 [CLKREGS_CDREX] = &dev_cmu_cdrex, 282 [CLKREGS_MEM ] = &dev_cmu_mem, 283}; 284 285struct clock_device { 286 void *mask[NCLKREGS]; 287}; 288 289 290struct clock_device * 291vm_install_ac_clock(vm_t *vm, enum vacdev_default default_ac, enum vacdev_action action) 292{ 293 struct clock_device *clkd; 294 int i; 295 uint8_t ac = (default_ac == VACDEV_DEFAULT_ALLOW) ? 0xff : 0x00; 296 /* Initialise private data */ 297 clkd = (struct clock_device *)calloc(1, sizeof(*clkd)); 298 if (clkd == NULL) { 299 return NULL; 300 } 301 for (i = 0; i < NCLKREGS; i++) { 302 int err; 303 if (clock_devices[i] == NULL) { 304 continue; 305 } 306 307 /* map device masks */ 308 clkd->mask[i] = calloc(1, BIT(12)); 309 if (clkd->mask[i] == NULL) { 310 return NULL; 311 } 312 memset(clkd->mask[i], ac, BIT(12)); 313 /* Install generic access control */ 314 err = vm_install_generic_ac_device(vm, clock_devices[i], clkd->mask[i], 315 BIT(12), action); 316 if (err) { 317 return NULL; 318 } 319 } 320 return clkd; 321} 322 323int vm_clock_config(struct clock_device *clkd, enum clk_id clk_id, int grant) 324{ 325 struct clock_data *data = &clock_data[clk_id]; 326 int i; 327 assert(data); 328 assert(data->nregs); 329 for (i = 0; i < data->nregs; i++) { 330 uint32_t *mask; 331 uint32_t mask_val; 332 mask = (uint32_t *)(clkd->mask[data->regs[i].bank] + data->regs[i].offset); 333 /* MASK(x) does not handle 32 bit masks */ 334 mask_val = ((1UL << data->regs[i].bits) - 1) << data->regs[i].shift; 335 if (grant) { 336 *mask |= mask_val; 337 } else { 338 *mask &= ~mask_val; 339 } 340 } 341 return 0; 342} 343 344int vm_clock_provide(struct clock_device *clkd, enum clk_id clk_id) 345{ 346 return vm_clock_config(clkd, clk_id, 1); 347} 348 349int vm_clock_restrict(struct clock_device *clkd, enum clk_id clk_id) 350{ 351 return vm_clock_config(clkd, clk_id, 0); 352} 353