1 /*
2  * Driver for Synopsys DesignWare MAC
3  *
4  * Copyright (c) 2021 BayLibre SAS
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * STM32H7X specific glue.
9  */
10 
11 
12 #define LOG_MODULE_NAME dwmac_plat
13 #define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
16 
17 /* be compatible with the HAL-based driver here */
18 #define DT_DRV_COMPAT st_stm32_ethernet
19 
20 #include <sys/types.h>
21 #include <zephyr/kernel.h>
22 #include <zephyr/net/ethernet.h>
23 #include <ethernet/eth.h>
24 #include <zephyr/drivers/clock_control.h>
25 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
26 #include <zephyr/drivers/pinctrl.h>
27 #include <zephyr/irq.h>
28 
29 #include "eth_dwmac_priv.h"
30 
31 PINCTRL_DT_INST_DEFINE(0);
32 static const struct pinctrl_dev_config *eth0_pcfg =
33 	PINCTRL_DT_INST_DEV_CONFIG_GET(0);
34 
35 static const struct stm32_pclken pclken = {
36 	.bus = DT_INST_CLOCKS_CELL_BY_NAME(0, stmmaceth, bus),
37 	.enr = DT_INST_CLOCKS_CELL_BY_NAME(0, stmmaceth, bits),
38 };
39 static const struct stm32_pclken pclken_tx = {
40 	.bus = DT_INST_CLOCKS_CELL_BY_NAME(0, mac_clk_tx, bus),
41 	.enr = DT_INST_CLOCKS_CELL_BY_NAME(0, mac_clk_tx, bits),
42 };
43 static const struct stm32_pclken pclken_rx = {
44 	.bus = DT_INST_CLOCKS_CELL_BY_NAME(0, mac_clk_rx, bus),
45 	.enr = DT_INST_CLOCKS_CELL_BY_NAME(0, mac_clk_rx, bits),
46 };
47 
dwmac_bus_init(struct dwmac_priv * p)48 int dwmac_bus_init(struct dwmac_priv *p)
49 {
50 	uint32_t reg_addr, reg_val;
51 	int ret;
52 
53 	p->clock = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
54 
55 	if (!device_is_ready(p->clock)) {
56 		LOG_ERR("clock control device not ready");
57 		return -ENODEV;
58 	}
59 
60 	ret  = clock_control_on(p->clock, (clock_control_subsys_t)&pclken);
61 	ret |= clock_control_on(p->clock, (clock_control_subsys_t)&pclken_tx);
62 	ret |= clock_control_on(p->clock, (clock_control_subsys_t)&pclken_rx);
63 	if (ret) {
64 		LOG_ERR("Failed to enable ethernet clock");
65 		return -EIO;
66 	}
67 
68 	ret = pinctrl_apply_state(eth0_pcfg, PINCTRL_STATE_DEFAULT);
69 	if (ret < 0) {
70 		LOG_ERR("Could not configure ethernet pins");
71 		return ret;
72 	}
73 
74 	/* set SYSCFGEN in RCC_APB4ENR */
75 	reg_addr = DT_REG_ADDR(DT_INST(0, st_stm32h7_rcc)) + 0xf4;
76 	reg_val = sys_read32(reg_addr);
77 	sys_write32(reg_val | BIT(1), reg_addr);
78 
79 	/* set RMII mode in SYSCFG_PMCR */
80 	reg_addr = 0x58000404;  /* no DT node? */
81 	reg_val = sys_read32(reg_addr);
82 	sys_write32(reg_val | 0x03800000, reg_addr);
83 
84 	p->base_addr = DT_INST_REG_ADDR(0);
85 	return 0;
86 }
87 
88 #if defined(CONFIG_NOCACHE_MEMORY)
89 #define __desc_mem __nocache __aligned(4)
90 #else
91 #error "missing memory attribute for descriptors"
92 #endif
93 
94 /* Descriptor rings in uncached memory */
95 static struct dwmac_dma_desc dwmac_tx_descs[NB_TX_DESCS] __desc_mem;
96 static struct dwmac_dma_desc dwmac_rx_descs[NB_RX_DESCS] __desc_mem;
97 
dwmac_platform_init(struct dwmac_priv * p)98 void dwmac_platform_init(struct dwmac_priv *p)
99 {
100 	p->tx_descs = dwmac_tx_descs;
101 	p->rx_descs = dwmac_rx_descs;
102 
103 	/* basic configuration for this platform */
104 	REG_WRITE(MAC_CONF,
105 		  MAC_CONF_PS |
106 		  MAC_CONF_FES |
107 		  MAC_CONF_DM);
108 	REG_WRITE(DMA_SYSBUS_MODE,
109 		  DMA_SYSBUS_MODE_AAL |
110 		  DMA_SYSBUS_MODE_FB);
111 
112 	/* set up IRQs (still masked for now) */
113 	IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), dwmac_isr,
114 		    DEVICE_DT_INST_GET(0), 0);
115 	irq_enable(DT_INST_IRQN(0));
116 
117 	/* create MAC address */
118 	gen_random_mac(p->mac_addr, 0x00, 0x80, 0xE1);
119 }
120 
121 /* Our private device instance */
122 static struct dwmac_priv dwmac_instance;
123 
124 ETH_NET_DEVICE_DT_INST_DEFINE(0,
125 			      dwmac_probe,
126 			      NULL,
127 			      &dwmac_instance,
128 			      NULL,
129 			      CONFIG_ETH_INIT_PRIORITY,
130 			      &dwmac_api,
131 			      NET_ETH_MTU);
132