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