1 /* 2 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com> 3 * 4 * Based on allwinner u-boot sources rsb code which is: 5 * (C) Copyright 2007-2013 6 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> 7 * lixiang <lixiang@allwinnertech.com> 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12 #include <common.h> 13 #include <errno.h> 14 #include <asm/arch/cpu.h> 15 #include <asm/arch/gpio.h> 16 #include <asm/arch/prcm.h> 17 #include <asm/arch/rsb.h> 18 19 static int rsb_set_device_mode(void); 20 21 static void rsb_cfg_io(void) 22 { 23 #ifdef CONFIG_MACH_SUN8I 24 sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL_R_RSB); 25 sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL_R_RSB); 26 sunxi_gpio_set_pull(SUNXI_GPL(0), 1); 27 sunxi_gpio_set_pull(SUNXI_GPL(1), 1); 28 sunxi_gpio_set_drv(SUNXI_GPL(0), 2); 29 sunxi_gpio_set_drv(SUNXI_GPL(1), 2); 30 #elif defined CONFIG_MACH_SUN9I 31 sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN_R_RSB); 32 sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN_R_RSB); 33 sunxi_gpio_set_pull(SUNXI_GPN(0), 1); 34 sunxi_gpio_set_pull(SUNXI_GPN(1), 1); 35 sunxi_gpio_set_drv(SUNXI_GPN(0), 2); 36 sunxi_gpio_set_drv(SUNXI_GPN(1), 2); 37 #else 38 #error unsupported MACH_SUNXI 39 #endif 40 } 41 42 static void rsb_set_clk(void) 43 { 44 struct sunxi_rsb_reg * const rsb = 45 (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; 46 u32 div = 0; 47 u32 cd_odly = 0; 48 49 /* Source is Hosc24M, set RSB clk to 3Mhz */ 50 div = 24000000 / 3000000 / 2 - 1; 51 cd_odly = div >> 1; 52 if (!cd_odly) 53 cd_odly = 1; 54 55 writel((cd_odly << 8) | div, &rsb->ccr); 56 } 57 58 int rsb_init(void) 59 { 60 struct sunxi_rsb_reg * const rsb = 61 (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; 62 63 /* Enable RSB and PIO clk, and de-assert their resets */ 64 prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB); 65 66 /* Setup external pins */ 67 rsb_cfg_io(); 68 69 writel(RSB_CTRL_SOFT_RST, &rsb->ctrl); 70 rsb_set_clk(); 71 72 return rsb_set_device_mode(); 73 } 74 75 static int rsb_await_trans(void) 76 { 77 struct sunxi_rsb_reg * const rsb = 78 (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; 79 unsigned long tmo = timer_get_us() + 1000000; 80 u32 stat; 81 int ret; 82 83 while (1) { 84 stat = readl(&rsb->stat); 85 if (stat & RSB_STAT_LBSY_INT) { 86 ret = -EBUSY; 87 break; 88 } 89 if (stat & RSB_STAT_TERR_INT) { 90 ret = -EIO; 91 break; 92 } 93 if (stat & RSB_STAT_TOVER_INT) { 94 ret = 0; 95 break; 96 } 97 if (timer_get_us() > tmo) { 98 ret = -ETIME; 99 break; 100 } 101 } 102 writel(stat, &rsb->stat); /* Clear status bits */ 103 104 return ret; 105 } 106 107 static int rsb_set_device_mode(void) 108 { 109 struct sunxi_rsb_reg * const rsb = 110 (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; 111 unsigned long tmo = timer_get_us() + 1000000; 112 113 writel(RSB_DMCR_DEVICE_MODE_START | RSB_DMCR_DEVICE_MODE_DATA, 114 &rsb->dmcr); 115 116 while (readl(&rsb->dmcr) & RSB_DMCR_DEVICE_MODE_START) { 117 if (timer_get_us() > tmo) 118 return -ETIME; 119 } 120 121 return rsb_await_trans(); 122 } 123 124 static int rsb_do_trans(void) 125 { 126 struct sunxi_rsb_reg * const rsb = 127 (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; 128 129 setbits_le32(&rsb->ctrl, RSB_CTRL_START_TRANS); 130 return rsb_await_trans(); 131 } 132 133 int rsb_set_device_address(u16 device_addr, u16 runtime_addr) 134 { 135 struct sunxi_rsb_reg * const rsb = 136 (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; 137 138 writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr) | 139 RSB_DEVADDR_DEVICE_ADDR(device_addr), &rsb->devaddr); 140 writel(RSB_CMD_SET_RTSADDR, &rsb->cmd); 141 142 return rsb_do_trans(); 143 } 144 145 int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data) 146 { 147 struct sunxi_rsb_reg * const rsb = 148 (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; 149 150 writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr); 151 writel(reg_addr, &rsb->addr); 152 writel(data, &rsb->data); 153 writel(RSB_CMD_BYTE_WRITE, &rsb->cmd); 154 155 return rsb_do_trans(); 156 } 157 158 int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data) 159 { 160 struct sunxi_rsb_reg * const rsb = 161 (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; 162 int ret; 163 164 writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr); 165 writel(reg_addr, &rsb->addr); 166 writel(RSB_CMD_BYTE_READ, &rsb->cmd); 167 168 ret = rsb_do_trans(); 169 if (ret) 170 return ret; 171 172 *data = readl(&rsb->data) & 0xff; 173 174 return 0; 175 } 176