11a2621baSYoshihiro Shimoda /*
21a2621baSYoshihiro Shimoda * Copyright (C) 2012 Renesas Solutions Corp.
31a2621baSYoshihiro Shimoda *
41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
51a2621baSYoshihiro Shimoda */
61a2621baSYoshihiro Shimoda
71a2621baSYoshihiro Shimoda #include <common.h>
81a2621baSYoshihiro Shimoda #include <malloc.h>
91a2621baSYoshihiro Shimoda #include <asm/processor.h>
101a2621baSYoshihiro Shimoda #include <asm/io.h>
111a2621baSYoshihiro Shimoda #include <asm/mmc.h>
12ff0960f9SSimon Glass #include <spi.h>
131a2621baSYoshihiro Shimoda #include <spi_flash.h>
141a2621baSYoshihiro Shimoda
checkboard(void)151a2621baSYoshihiro Shimoda int checkboard(void)
161a2621baSYoshihiro Shimoda {
171a2621baSYoshihiro Shimoda puts("BOARD: SH7752 evaluation board (R0P7752C00000RZ)\n");
181a2621baSYoshihiro Shimoda
191a2621baSYoshihiro Shimoda return 0;
201a2621baSYoshihiro Shimoda }
211a2621baSYoshihiro Shimoda
init_gpio(void)221a2621baSYoshihiro Shimoda static void init_gpio(void)
231a2621baSYoshihiro Shimoda {
241a2621baSYoshihiro Shimoda struct gpio_regs *gpio = GPIO_BASE;
251a2621baSYoshihiro Shimoda struct sermux_regs *sermux = SERMUX_BASE;
261a2621baSYoshihiro Shimoda
271a2621baSYoshihiro Shimoda /* GPIO */
281a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pacr); /* GETHER */
291a2621baSYoshihiro Shimoda writew(0x0001, &gpio->pbcr); /* INTC */
301a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pccr); /* PWMU, INTC */
311a2621baSYoshihiro Shimoda writew(0xeaff, &gpio->pecr); /* GPIO */
321a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pfcr); /* WDT */
331a2621baSYoshihiro Shimoda writew(0x0000, &gpio->phcr); /* SPI1 */
341a2621baSYoshihiro Shimoda writew(0x0000, &gpio->picr); /* SDHI */
351a2621baSYoshihiro Shimoda writew(0x0003, &gpio->pkcr); /* SerMux */
361a2621baSYoshihiro Shimoda writew(0x0000, &gpio->plcr); /* SerMux */
371a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pmcr); /* RIIC */
381a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pncr); /* USB, SGPIO */
391a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pocr); /* SGPIO */
401a2621baSYoshihiro Shimoda writew(0xd555, &gpio->pqcr); /* GPIO */
411a2621baSYoshihiro Shimoda writew(0x0000, &gpio->prcr); /* RIIC */
421a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pscr); /* RIIC */
431a2621baSYoshihiro Shimoda writeb(0x00, &gpio->pudr);
441a2621baSYoshihiro Shimoda writew(0x5555, &gpio->pucr); /* Debug LED */
451a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pvcr); /* RSPI */
461a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pwcr); /* EVC */
471a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pxcr); /* LBSC */
481a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pycr); /* LBSC */
491a2621baSYoshihiro Shimoda writew(0x0000, &gpio->pzcr); /* eMMC */
501a2621baSYoshihiro Shimoda writew(0xfe00, &gpio->psel0);
511a2621baSYoshihiro Shimoda writew(0xff00, &gpio->psel3);
521a2621baSYoshihiro Shimoda writew(0x771f, &gpio->psel4);
531a2621baSYoshihiro Shimoda writew(0x00ff, &gpio->psel6);
541a2621baSYoshihiro Shimoda writew(0xfc00, &gpio->psel7);
551a2621baSYoshihiro Shimoda
561a2621baSYoshihiro Shimoda writeb(0x10, &sermux->smr0); /* SMR0: SerMux mode 0 */
571a2621baSYoshihiro Shimoda }
581a2621baSYoshihiro Shimoda
init_usb_phy(void)591a2621baSYoshihiro Shimoda static void init_usb_phy(void)
601a2621baSYoshihiro Shimoda {
611a2621baSYoshihiro Shimoda struct usb_common_regs *common0 = USB0_COMMON_BASE;
621a2621baSYoshihiro Shimoda struct usb_common_regs *common1 = USB1_COMMON_BASE;
631a2621baSYoshihiro Shimoda struct usb0_phy_regs *phy = USB0_PHY_BASE;
641a2621baSYoshihiro Shimoda struct usb1_port_regs *port = USB1_PORT_BASE;
651a2621baSYoshihiro Shimoda struct usb1_alignment_regs *align = USB1_ALIGNMENT_BASE;
661a2621baSYoshihiro Shimoda
671a2621baSYoshihiro Shimoda writew(0x0100, &phy->reset); /* set reset */
681a2621baSYoshihiro Shimoda /* port0 = USB0, port1 = USB1 */
691a2621baSYoshihiro Shimoda writew(0x0002, &phy->portsel);
701a2621baSYoshihiro Shimoda writel(0x0001, &port->port1sel); /* port1 = Host */
711a2621baSYoshihiro Shimoda writew(0x0111, &phy->reset); /* clear reset */
721a2621baSYoshihiro Shimoda
731a2621baSYoshihiro Shimoda writew(0x4000, &common0->suspmode);
741a2621baSYoshihiro Shimoda writew(0x4000, &common1->suspmode);
751a2621baSYoshihiro Shimoda
761a2621baSYoshihiro Shimoda #if defined(__LITTLE_ENDIAN)
771a2621baSYoshihiro Shimoda writel(0x00000000, &align->ehcidatac);
781a2621baSYoshihiro Shimoda writel(0x00000000, &align->ohcidatac);
791a2621baSYoshihiro Shimoda #endif
801a2621baSYoshihiro Shimoda }
811a2621baSYoshihiro Shimoda
init_gether_mdio(void)821a2621baSYoshihiro Shimoda static void init_gether_mdio(void)
831a2621baSYoshihiro Shimoda {
841a2621baSYoshihiro Shimoda struct gpio_regs *gpio = GPIO_BASE;
851a2621baSYoshihiro Shimoda
861a2621baSYoshihiro Shimoda writew(readw(&gpio->pgcr) | 0x0004, &gpio->pgcr);
871a2621baSYoshihiro Shimoda writeb(readb(&gpio->pgdr) | 0x02, &gpio->pgdr); /* Use ET0-MDIO */
881a2621baSYoshihiro Shimoda }
891a2621baSYoshihiro Shimoda
set_mac_to_sh_giga_eth_register(int channel,char * mac_string)901a2621baSYoshihiro Shimoda static void set_mac_to_sh_giga_eth_register(int channel, char *mac_string)
911a2621baSYoshihiro Shimoda {
921a2621baSYoshihiro Shimoda struct ether_mac_regs *ether;
931a2621baSYoshihiro Shimoda unsigned char mac[6];
941a2621baSYoshihiro Shimoda unsigned long val;
951a2621baSYoshihiro Shimoda
961a2621baSYoshihiro Shimoda eth_parse_enetaddr(mac_string, mac);
971a2621baSYoshihiro Shimoda
981a2621baSYoshihiro Shimoda if (!channel)
991a2621baSYoshihiro Shimoda ether = GETHER0_MAC_BASE;
1001a2621baSYoshihiro Shimoda else
1011a2621baSYoshihiro Shimoda ether = GETHER1_MAC_BASE;
1021a2621baSYoshihiro Shimoda
1031a2621baSYoshihiro Shimoda val = (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3];
1041a2621baSYoshihiro Shimoda writel(val, ðer->mahr);
1051a2621baSYoshihiro Shimoda val = (mac[4] << 8) | mac[5];
1061a2621baSYoshihiro Shimoda writel(val, ðer->malr);
1071a2621baSYoshihiro Shimoda }
1081a2621baSYoshihiro Shimoda
1091a2621baSYoshihiro Shimoda /*****************************************************************
1101a2621baSYoshihiro Shimoda * This PMB must be set on this timing. The lowlevel_init is run on
1111a2621baSYoshihiro Shimoda * Area 0(phys 0x00000000), so we have to map it.
1121a2621baSYoshihiro Shimoda *
1131a2621baSYoshihiro Shimoda * The new PMB table is following:
1141a2621baSYoshihiro Shimoda * ent virt phys v sz c wt
1151a2621baSYoshihiro Shimoda * 0 0xa0000000 0x40000000 1 128M 0 1
1161a2621baSYoshihiro Shimoda * 1 0xa8000000 0x48000000 1 128M 0 1
1171a2621baSYoshihiro Shimoda * 2 0xb0000000 0x50000000 1 128M 0 1
1181a2621baSYoshihiro Shimoda * 3 0xb8000000 0x58000000 1 128M 0 1
1191a2621baSYoshihiro Shimoda * 4 0x80000000 0x40000000 1 128M 1 1
1201a2621baSYoshihiro Shimoda * 5 0x88000000 0x48000000 1 128M 1 1
1211a2621baSYoshihiro Shimoda * 6 0x90000000 0x50000000 1 128M 1 1
1221a2621baSYoshihiro Shimoda * 7 0x98000000 0x58000000 1 128M 1 1
1231a2621baSYoshihiro Shimoda */
set_pmb_on_board_init(void)1241a2621baSYoshihiro Shimoda static void set_pmb_on_board_init(void)
1251a2621baSYoshihiro Shimoda {
1261a2621baSYoshihiro Shimoda struct mmu_regs *mmu = MMU_BASE;
1271a2621baSYoshihiro Shimoda
1281a2621baSYoshihiro Shimoda /* clear ITLB */
1291a2621baSYoshihiro Shimoda writel(0x00000004, &mmu->mmucr);
1301a2621baSYoshihiro Shimoda
1311a2621baSYoshihiro Shimoda /* delete PMB for SPIBOOT */
1321a2621baSYoshihiro Shimoda writel(0, PMB_ADDR_BASE(0));
1331a2621baSYoshihiro Shimoda writel(0, PMB_DATA_BASE(0));
1341a2621baSYoshihiro Shimoda
1351a2621baSYoshihiro Shimoda /* add PMB for SDRAM(0x40000000 - 0x47ffffff) */
1361a2621baSYoshihiro Shimoda /* ppn ub v s1 s0 c wt */
1371a2621baSYoshihiro Shimoda writel(mk_pmb_addr_val(0xa0), PMB_ADDR_BASE(0));
1381a2621baSYoshihiro Shimoda writel(mk_pmb_data_val(0x40, 1, 1, 1, 0, 0, 1), PMB_DATA_BASE(0));
1391a2621baSYoshihiro Shimoda writel(mk_pmb_addr_val(0xb0), PMB_ADDR_BASE(2));
1401a2621baSYoshihiro Shimoda writel(mk_pmb_data_val(0x50, 1, 1, 1, 0, 0, 1), PMB_DATA_BASE(2));
1411a2621baSYoshihiro Shimoda writel(mk_pmb_addr_val(0xb8), PMB_ADDR_BASE(3));
1421a2621baSYoshihiro Shimoda writel(mk_pmb_data_val(0x58, 1, 1, 1, 0, 0, 1), PMB_DATA_BASE(3));
1431a2621baSYoshihiro Shimoda writel(mk_pmb_addr_val(0x80), PMB_ADDR_BASE(4));
1441a2621baSYoshihiro Shimoda writel(mk_pmb_data_val(0x40, 0, 1, 1, 0, 1, 1), PMB_DATA_BASE(4));
1451a2621baSYoshihiro Shimoda writel(mk_pmb_addr_val(0x90), PMB_ADDR_BASE(6));
1461a2621baSYoshihiro Shimoda writel(mk_pmb_data_val(0x50, 0, 1, 1, 0, 1, 1), PMB_DATA_BASE(6));
1471a2621baSYoshihiro Shimoda writel(mk_pmb_addr_val(0x98), PMB_ADDR_BASE(7));
1481a2621baSYoshihiro Shimoda writel(mk_pmb_data_val(0x58, 0, 1, 1, 0, 1, 1), PMB_DATA_BASE(7));
1491a2621baSYoshihiro Shimoda }
1501a2621baSYoshihiro Shimoda
board_init(void)1511a2621baSYoshihiro Shimoda int board_init(void)
1521a2621baSYoshihiro Shimoda {
1531a2621baSYoshihiro Shimoda init_gpio();
1541a2621baSYoshihiro Shimoda set_pmb_on_board_init();
1551a2621baSYoshihiro Shimoda
1561a2621baSYoshihiro Shimoda init_usb_phy();
1571a2621baSYoshihiro Shimoda init_gether_mdio();
1581a2621baSYoshihiro Shimoda
1591a2621baSYoshihiro Shimoda return 0;
1601a2621baSYoshihiro Shimoda }
1611a2621baSYoshihiro Shimoda
board_mmc_init(bd_t * bis)1621a2621baSYoshihiro Shimoda int board_mmc_init(bd_t *bis)
1631a2621baSYoshihiro Shimoda {
1641a2621baSYoshihiro Shimoda struct gpio_regs *gpio = GPIO_BASE;
1651a2621baSYoshihiro Shimoda
1661a2621baSYoshihiro Shimoda writew(readw(&gpio->pgcr) | 0x0040, &gpio->pgcr);
1671a2621baSYoshihiro Shimoda writeb(readb(&gpio->pgdr) & ~0x08, &gpio->pgdr); /* Reset */
1681a2621baSYoshihiro Shimoda udelay(1);
1691a2621baSYoshihiro Shimoda writeb(readb(&gpio->pgdr) | 0x08, &gpio->pgdr); /* Release reset */
1701a2621baSYoshihiro Shimoda udelay(200);
1711a2621baSYoshihiro Shimoda
1721a2621baSYoshihiro Shimoda return mmcif_mmc_init();
1731a2621baSYoshihiro Shimoda }
1741a2621baSYoshihiro Shimoda
get_sh_eth_mac_raw(unsigned char * buf,int size)1751a2621baSYoshihiro Shimoda static int get_sh_eth_mac_raw(unsigned char *buf, int size)
1761a2621baSYoshihiro Shimoda {
1771a2621baSYoshihiro Shimoda struct spi_flash *spi;
1781a2621baSYoshihiro Shimoda int ret;
1791a2621baSYoshihiro Shimoda
1801a2621baSYoshihiro Shimoda spi = spi_flash_probe(0, 0, 1000000, SPI_MODE_3);
1811a2621baSYoshihiro Shimoda if (spi == NULL) {
1821a2621baSYoshihiro Shimoda printf("%s: spi_flash probe failed.\n", __func__);
1831a2621baSYoshihiro Shimoda return 1;
1841a2621baSYoshihiro Shimoda }
1851a2621baSYoshihiro Shimoda
1861a2621baSYoshihiro Shimoda ret = spi_flash_read(spi, SH7752EVB_ETHERNET_MAC_BASE, size, buf);
1871a2621baSYoshihiro Shimoda if (ret) {
1881a2621baSYoshihiro Shimoda printf("%s: spi_flash read failed.\n", __func__);
1891a2621baSYoshihiro Shimoda spi_flash_free(spi);
1901a2621baSYoshihiro Shimoda return 1;
1911a2621baSYoshihiro Shimoda }
1921a2621baSYoshihiro Shimoda spi_flash_free(spi);
1931a2621baSYoshihiro Shimoda
1941a2621baSYoshihiro Shimoda return 0;
1951a2621baSYoshihiro Shimoda }
1961a2621baSYoshihiro Shimoda
get_sh_eth_mac(int channel,char * mac_string,unsigned char * buf)1971a2621baSYoshihiro Shimoda static int get_sh_eth_mac(int channel, char *mac_string, unsigned char *buf)
1981a2621baSYoshihiro Shimoda {
1991a2621baSYoshihiro Shimoda memcpy(mac_string, &buf[channel * (SH7752EVB_ETHERNET_MAC_SIZE + 1)],
2001a2621baSYoshihiro Shimoda SH7752EVB_ETHERNET_MAC_SIZE);
2011a2621baSYoshihiro Shimoda mac_string[SH7752EVB_ETHERNET_MAC_SIZE] = 0x00; /* terminate */
2021a2621baSYoshihiro Shimoda
2031a2621baSYoshihiro Shimoda return 0;
2041a2621baSYoshihiro Shimoda }
2051a2621baSYoshihiro Shimoda
init_ethernet_mac(void)2061a2621baSYoshihiro Shimoda static void init_ethernet_mac(void)
2071a2621baSYoshihiro Shimoda {
2081a2621baSYoshihiro Shimoda char mac_string[64];
2091a2621baSYoshihiro Shimoda char env_string[64];
2101a2621baSYoshihiro Shimoda int i;
2111a2621baSYoshihiro Shimoda unsigned char *buf;
2121a2621baSYoshihiro Shimoda
2131a2621baSYoshihiro Shimoda buf = malloc(256);
2141a2621baSYoshihiro Shimoda if (!buf) {
2151a2621baSYoshihiro Shimoda printf("%s: malloc failed.\n", __func__);
2161a2621baSYoshihiro Shimoda return;
2171a2621baSYoshihiro Shimoda }
2181a2621baSYoshihiro Shimoda get_sh_eth_mac_raw(buf, 256);
2191a2621baSYoshihiro Shimoda
2201a2621baSYoshihiro Shimoda /* Gigabit Ethernet */
2211a2621baSYoshihiro Shimoda for (i = 0; i < SH7752EVB_ETHERNET_NUM_CH; i++) {
2221a2621baSYoshihiro Shimoda get_sh_eth_mac(i, mac_string, buf);
2231a2621baSYoshihiro Shimoda if (i == 0)
224*382bee57SSimon Glass env_set("ethaddr", mac_string);
2251a2621baSYoshihiro Shimoda else {
2261a2621baSYoshihiro Shimoda sprintf(env_string, "eth%daddr", i);
227*382bee57SSimon Glass env_set(env_string, mac_string);
2281a2621baSYoshihiro Shimoda }
2291a2621baSYoshihiro Shimoda set_mac_to_sh_giga_eth_register(i, mac_string);
2301a2621baSYoshihiro Shimoda }
2311a2621baSYoshihiro Shimoda
2321a2621baSYoshihiro Shimoda free(buf);
2331a2621baSYoshihiro Shimoda }
2341a2621baSYoshihiro Shimoda
board_late_init(void)2351a2621baSYoshihiro Shimoda int board_late_init(void)
2361a2621baSYoshihiro Shimoda {
2371a2621baSYoshihiro Shimoda init_ethernet_mac();
2381a2621baSYoshihiro Shimoda
2391a2621baSYoshihiro Shimoda return 0;
2401a2621baSYoshihiro Shimoda }
2411a2621baSYoshihiro Shimoda
do_write_mac(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])2421a2621baSYoshihiro Shimoda int do_write_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2431a2621baSYoshihiro Shimoda {
2441a2621baSYoshihiro Shimoda int i, ret;
2451a2621baSYoshihiro Shimoda char mac_string[256];
2461a2621baSYoshihiro Shimoda struct spi_flash *spi;
2471a2621baSYoshihiro Shimoda unsigned char *buf;
2481a2621baSYoshihiro Shimoda
2491a2621baSYoshihiro Shimoda if (argc != 3) {
2501a2621baSYoshihiro Shimoda buf = malloc(256);
2511a2621baSYoshihiro Shimoda if (!buf) {
2521a2621baSYoshihiro Shimoda printf("%s: malloc failed.\n", __func__);
2531a2621baSYoshihiro Shimoda return 1;
2541a2621baSYoshihiro Shimoda }
2551a2621baSYoshihiro Shimoda
2561a2621baSYoshihiro Shimoda get_sh_eth_mac_raw(buf, 256);
2571a2621baSYoshihiro Shimoda
2581a2621baSYoshihiro Shimoda /* print current MAC address */
2591a2621baSYoshihiro Shimoda for (i = 0; i < SH7752EVB_ETHERNET_NUM_CH; i++) {
2601a2621baSYoshihiro Shimoda get_sh_eth_mac(i, mac_string, buf);
2611a2621baSYoshihiro Shimoda printf("GETHERC ch%d = %s\n", i, mac_string);
2621a2621baSYoshihiro Shimoda }
2631a2621baSYoshihiro Shimoda free(buf);
2641a2621baSYoshihiro Shimoda return 0;
2651a2621baSYoshihiro Shimoda }
2661a2621baSYoshihiro Shimoda
2671a2621baSYoshihiro Shimoda /* new setting */
2681a2621baSYoshihiro Shimoda memset(mac_string, 0xff, sizeof(mac_string));
2691a2621baSYoshihiro Shimoda sprintf(mac_string, "%s\t%s",
2701a2621baSYoshihiro Shimoda argv[1], argv[2]);
2711a2621baSYoshihiro Shimoda
2721a2621baSYoshihiro Shimoda /* write MAC data to SPI rom */
2731a2621baSYoshihiro Shimoda spi = spi_flash_probe(0, 0, 1000000, SPI_MODE_3);
2741a2621baSYoshihiro Shimoda if (!spi) {
2751a2621baSYoshihiro Shimoda printf("%s: spi_flash probe failed.\n", __func__);
2761a2621baSYoshihiro Shimoda return 1;
2771a2621baSYoshihiro Shimoda }
2781a2621baSYoshihiro Shimoda
2791a2621baSYoshihiro Shimoda ret = spi_flash_erase(spi, SH7752EVB_ETHERNET_MAC_BASE_SPI,
2801a2621baSYoshihiro Shimoda SH7752EVB_SPI_SECTOR_SIZE);
2811a2621baSYoshihiro Shimoda if (ret) {
2821a2621baSYoshihiro Shimoda printf("%s: spi_flash erase failed.\n", __func__);
2831a2621baSYoshihiro Shimoda return 1;
2841a2621baSYoshihiro Shimoda }
2851a2621baSYoshihiro Shimoda
2861a2621baSYoshihiro Shimoda ret = spi_flash_write(spi, SH7752EVB_ETHERNET_MAC_BASE_SPI,
2871a2621baSYoshihiro Shimoda sizeof(mac_string), mac_string);
2881a2621baSYoshihiro Shimoda if (ret) {
2891a2621baSYoshihiro Shimoda printf("%s: spi_flash write failed.\n", __func__);
2901a2621baSYoshihiro Shimoda spi_flash_free(spi);
2911a2621baSYoshihiro Shimoda return 1;
2921a2621baSYoshihiro Shimoda }
2931a2621baSYoshihiro Shimoda spi_flash_free(spi);
2941a2621baSYoshihiro Shimoda
2951a2621baSYoshihiro Shimoda puts("The writing of the MAC address to SPI ROM was completed.\n");
2961a2621baSYoshihiro Shimoda
2971a2621baSYoshihiro Shimoda return 0;
2981a2621baSYoshihiro Shimoda }
2991a2621baSYoshihiro Shimoda
3001a2621baSYoshihiro Shimoda U_BOOT_CMD(
3011a2621baSYoshihiro Shimoda write_mac, 3, 1, do_write_mac,
3021a2621baSYoshihiro Shimoda "write MAC address for GETHERC",
3031a2621baSYoshihiro Shimoda "[GETHERC ch0] [GETHERC ch1]\n"
3041a2621baSYoshihiro Shimoda );
305