1 /*
2  * Copyright (c) 2022 Basalte bv
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT atmel_sam_smc
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/pinctrl.h>
11 #include <zephyr/drivers/clock_control/atmel_sam_pmc.h>
12 #include <soc.h>
13 
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(memc_sam, CONFIG_MEMC_LOG_LEVEL);
16 
17 struct memc_smc_bank_config {
18 	uint32_t cs;
19 	uint32_t mode;
20 	uint32_t setup_timing;
21 	uint32_t pulse_timing;
22 	uint32_t cycle_timing;
23 };
24 
25 struct memc_smc_config {
26 	Smc *regs;
27 	size_t banks_len;
28 	const struct memc_smc_bank_config *banks;
29 	const struct atmel_sam_pmc_config clock_cfg;
30 	const struct pinctrl_dev_config *pcfg;
31 };
32 
memc_smc_init(const struct device * dev)33 static int memc_smc_init(const struct device *dev)
34 {
35 	int ret;
36 	const struct memc_smc_config *cfg = dev->config;
37 	SmcCs_number *bank;
38 
39 	/* Enable SMC clock in PMC */
40 	(void)clock_control_on(SAM_DT_PMC_CONTROLLER,
41 			       (clock_control_subsys_t)&cfg->clock_cfg);
42 
43 	ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
44 	if (ret < 0) {
45 		return ret;
46 	}
47 
48 	for (size_t i = 0U; i < cfg->banks_len; i++) {
49 		if (cfg->banks[i].cs >= SMCCS_NUMBER_NUMBER) {
50 			return -EINVAL;
51 		}
52 
53 		bank = &cfg->regs->SMC_CS_NUMBER[cfg->banks[i].cs];
54 
55 		bank->SMC_SETUP = cfg->banks[i].setup_timing;
56 		bank->SMC_PULSE = cfg->banks[i].pulse_timing;
57 		bank->SMC_CYCLE = cfg->banks[i].cycle_timing;
58 		bank->SMC_MODE = cfg->banks[i].mode;
59 	}
60 
61 	return 0;
62 }
63 
64 #define SETUP_TIMING(node_id)								\
65 	SMC_SETUP_NWE_SETUP(DT_PROP_BY_IDX(node_id, atmel_smc_setup_timing, 0))		\
66 	| SMC_SETUP_NCS_WR_SETUP(DT_PROP_BY_IDX(node_id, atmel_smc_setup_timing, 1))	\
67 	| SMC_SETUP_NRD_SETUP(DT_PROP_BY_IDX(node_id, atmel_smc_setup_timing, 2))	\
68 	| SMC_SETUP_NCS_RD_SETUP(DT_PROP_BY_IDX(node_id, atmel_smc_setup_timing, 3))
69 #define PULSE_TIMING(node_id)								\
70 	SMC_PULSE_NWE_PULSE(DT_PROP_BY_IDX(node_id, atmel_smc_pulse_timing, 0))		\
71 	| SMC_PULSE_NCS_WR_PULSE(DT_PROP_BY_IDX(node_id, atmel_smc_pulse_timing, 1))	\
72 	| SMC_PULSE_NRD_PULSE(DT_PROP_BY_IDX(node_id, atmel_smc_pulse_timing, 2))	\
73 	| SMC_PULSE_NCS_RD_PULSE(DT_PROP_BY_IDX(node_id, atmel_smc_pulse_timing, 3))
74 #define CYCLE_TIMING(node_id)								\
75 	SMC_CYCLE_NWE_CYCLE(DT_PROP_BY_IDX(node_id, atmel_smc_cycle_timing, 0))		\
76 	| SMC_CYCLE_NRD_CYCLE(DT_PROP_BY_IDX(node_id, atmel_smc_cycle_timing, 1))
77 
78 #define BANK_CONFIG(node_id)								\
79 	{										\
80 		.cs = DT_REG_ADDR(node_id),						\
81 		.mode = COND_CODE_1(DT_ENUM_IDX(node_id, atmel_smc_write_mode),		\
82 				    (SMC_MODE_WRITE_MODE), (0))				\
83 			| COND_CODE_1(DT_ENUM_IDX(node_id, atmel_smc_read_mode),	\
84 				      (SMC_MODE_READ_MODE), (0)),			\
85 		.setup_timing = SETUP_TIMING(node_id),					\
86 		.pulse_timing = PULSE_TIMING(node_id),					\
87 		.cycle_timing = CYCLE_TIMING(node_id),					\
88 	},
89 
90 #define MEMC_SMC_DEFINE(inst)								\
91 	static const struct memc_smc_bank_config smc_bank_config_##inst[] = {		\
92 		DT_INST_FOREACH_CHILD(inst, BANK_CONFIG)				\
93 	};										\
94 	PINCTRL_DT_INST_DEFINE(inst);							\
95 	static const struct memc_smc_config smc_config_##inst = {			\
96 		.regs = (Smc *)DT_INST_REG_ADDR(inst),					\
97 		.clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(inst),				\
98 		.banks_len = ARRAY_SIZE(smc_bank_config_##inst),			\
99 		.banks = smc_bank_config_##inst,					\
100 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst),				\
101 	};										\
102 	DEVICE_DT_INST_DEFINE(inst, memc_smc_init, NULL, NULL,				\
103 			      &smc_config_##inst, POST_KERNEL,				\
104 			      CONFIG_MEMC_INIT_PRIORITY, NULL);
105 
106 DT_INST_FOREACH_STATUS_OKAY(MEMC_SMC_DEFINE)
107