#include #include "Soc.h" #include #include #include #include #include #if 0 /* Not used or exisit register and configure */ #define NA -1 #define BIT(n) (1 << (n)) #define RK806_DBG DEBUG_ERROR /* rk806 buck*/ #define RK806_BUCK_ON_VSEL(n) (0x1a + n - 1) #define RK806_BUCK_SLP_VSEL(n) (0x24 + n - 1) #define RK806_BUCK_CONFIG(n) (0x10 + n - 1) #define RK806_BUCK_VSEL_MASK 0xff /* RK806 LDO */ #define RK806_NLDO_ON_VSEL(n) (0x43 + n - 1) #define RK806_NLDO_SLP_VSEL(n) (0x48 + n - 1) #define RK806_NLDO_VSEL_MASK 0xff #define RK806_PLDO_ON_VSEL(n) (0x4e + n - 1) #define RK806_PLDO_SLP_VSEL(n) (0x54 + n - 1) #define RK806_PLDO_VSEL_MASK 0xff /* RK806 ENABLE */ #define RK806_POWER_EN(n) (0x00 + n) #define RK806_NLDO_EN(n) (0x03 + n) #define RK806_PLDO_EN(n) (0x04 + n) #define RK806_RAMP_RATE_MASK1 0xc0 #define RK806_RAMP_RATE_REG1(n) (0x10 + n) #define RK806_RAMP_RATE_REG1_8 0xeb #define RK806_RAMP_RATE_REG9_10 0xea #define RK806_RAMP_RATE_4LSB_PER_1CLK 0x00/* LDO 100mV/uS buck 50mV/us */ #define RK806_RAMP_RATE_2LSB_PER_1CLK 0x01/* LDO 50mV/uS buck 25mV/us */ #define RK806_RAMP_RATE_1LSB_PER_1CLK 0x02/* LDO 25mV/uS buck 12.5mV/us */ #define RK806_RAMP_RATE_1LSB_PER_2CLK 0x03/* LDO 12.5mV/uS buck 6.25mV/us */ #define RK806_RAMP_RATE_1LSB_PER_4CLK 0x04/* LDO 6.28/2mV/uS buck 3.125mV/us */ #define RK806_RAMP_RATE_1LSB_PER_8CLK 0x05/* LDO 3.12mV/uS buck 1.56mV/us */ #define RK806_RAMP_RATE_1LSB_PER_13CLK 0x06/* LDO 1.9mV/uS buck 961mV/us */ #define RK806_RAMP_RATE_1LSB_PER_32CLK 0x07/* LDO 0.78mV/uS buck 0.39mV/us */ #define RK806_PLDO0_2_MSK(pldo) (BIT(pldo + 5)) #define RK806_PLDO0_2_SET(pldo) (BIT(pldo + 1) | RK806_PLDO0_2_MSK(pldo)) #define RK806_PLDO0_2_CLR(pldo) RK806_PLDO0_2_MSK(pldo) #define RK806_CHIP_NAME 0x5A #define RK806_CHIP_VER 0x5B #define RK806_CMD_READ 0 #define RK806_CMD_WRITE BIT(7) #define RK806_CMD_CRC_EN BIT(6) #define RK806_CMD_CRC_DIS 0 #define RK806_CMD_LEN_MSK 0x0f #define RK806_REG_H 0x00 #define RK806_SYS_CFG1 0x5f #define RK806_SYS_CFG3 0x72 #define RK806_PWRON_KEY 0x76 #define RK806_INT_STS0 0x77 #define RK806_INT_MSK0 0x78 #define RK806_INT_STS1 0x79 #define RK806_INT_MSK1 0x7A #define RK806_GPIO_INT_CONFIG 0x7B #define RK806_IRQ_PWRON_FALL_MSK BIT(0) #define RK806_IRQ_PWRON_RISE_MSK BIT(1) #define RK806_DEV_OFF BIT(0) #define RK806_RST_MODE1 0x01 #define RK806_RST_MODE2 0x02 #define VERSION_AB 0x01 struct regulator_init_data { const char *supply_regulator; /* or NULL for system supply */ INT32 reg_id; INT32 init_voltage_mv; }; struct rk8xx_reg_info { UINT32 min_uv; UINT32 step_uv; UINT8 vsel_reg; UINT8 vsel_sleep_reg; UINT8 config_reg; UINT8 vsel_mask; UINT8 min_sel; /* only for buck now */ UINT8 max_sel; UINT8 range_num; }; #define RK8XX_DESC_COM(_name, _reg_info, _ops) \ { \ .reg_info = (_reg_info), \ .name = (_reg_id), \ .ops = _ops, \ } #define RK8XX_VOLTAGE_INIT(_id, _voltage) \ { \ .reg_id = (_id),\ .init_voltage_mv = (_voltage),\ } /****************************************** 8 -12: MASTER, SLAVE 4 -7: BUCK, NLDO, PLDO 0 -3: num ******************************************/ #define MASTER (0x0 << 8) #define SLAVER (0x1 << 8) #define BUCK (0x0 << 4) #define NLDO (0x1 << 4) #define PLDO (0x2 << 4) enum master_num { MASTER_BUCK1 = (MASTER | BUCK | 0), MASTER_BUCK2 = (MASTER | BUCK | 1), MASTER_BUCK3 = (MASTER | BUCK | 2), MASTER_BUCK4 = (MASTER | BUCK | 3), MASTER_BUCK5 = (MASTER | BUCK | 4), MASTER_BUCK6 = (MASTER | BUCK | 5), MASTER_BUCK7 = (MASTER | BUCK | 6), MASTER_BUCK8 = (MASTER | BUCK | 7), MASTER_BUCK9 = (MASTER | BUCK | 8), MASTER_BUCK10 = (MASTER | BUCK | 9), MASTER_NLDO1 = (MASTER | NLDO | 0), MASTER_NLDO2 = (MASTER | NLDO | 1), MASTER_NLDO3 = (MASTER | NLDO | 2), MASTER_NLDO4 = (MASTER | NLDO | 3), MASTER_NLDO5 = (MASTER | NLDO | 4), MASTER_PLDO1 = (MASTER | PLDO | 0), MASTER_PLDO2 = (MASTER | PLDO | 1), MASTER_PLDO3 = (MASTER | PLDO | 2), MASTER_PLDO4 = (MASTER | PLDO | 3), MASTER_PLDO5 = (MASTER | PLDO | 4), MASTER_PLDO6 = (MASTER | PLDO | 5), }; enum slaver_num { SLAVER_BUCK1 = (SLAVER | BUCK | 0), SLAVER_BUCK2 = (SLAVER | BUCK | 1), SLAVER_BUCK3 = (SLAVER | BUCK | 2), SLAVER_BUCK4 = (SLAVER | BUCK | 3), SLAVER_BUCK5 = (SLAVER | BUCK | 4), SLAVER_BUCK6 = (SLAVER | BUCK | 5), SLAVER_BUCK7 = (SLAVER | BUCK | 6), SLAVER_BUCK8 = (SLAVER | BUCK | 7), SLAVER_BUCK9 = (SLAVER | BUCK | 8), SLAVER_BUCK10 = (SLAVER | BUCK | 9), SLAVER_NLDO1 = (SLAVER | NLDO | 0), SLAVER_NLDO2 = (SLAVER | NLDO | 1), SLAVER_NLDO3 = (SLAVER | NLDO | 2), SLAVER_NLDO4 = (SLAVER | NLDO | 3), SLAVER_NLDO5 = (SLAVER | NLDO | 4), SLAVER_PLDO1 = (SLAVER | PLDO | 0), SLAVER_PLDO2 = (SLAVER | PLDO | 1), SLAVER_PLDO3 = (SLAVER | PLDO | 2), SLAVER_PLDO4 = (SLAVER | PLDO | 3), SLAVER_PLDO5 = (SLAVER | PLDO | 4), SLAVER_PLDO6 = (SLAVER | PLDO | 5), }; #endif struct SPI_HANDLE gSPI; static const struct rk8xx_reg_info rk806_buck[] = { /* buck 1 */ { 500000, 6250, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0x00, 0xa0, 3}, { 1500000, 25000, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xa1, 0xed, 3}, { 3400000, 0, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xee, 0xff, 3}, /* buck 2 */ { 500000, 6250, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0x00, 0xa0, 3}, { 1500000, 25000, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xa1, 0xed, 3}, { 3400000, 0, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xee, 0xff, 3}, /* buck 3 */ { 500000, 6250, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0x00, 0xa0, 3}, { 1500000, 25000, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xa1, 0xed, 3}, { 3400000, 0, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xee, 0xff, 3}, /* buck 4 */ { 500000, 6250, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0x00, 0xa0, 3}, { 1500000, 25000, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xa1, 0xed, 3}, { 3400000, 0, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xee, 0xff, 3}, /* buck 5 */ { 500000, 6250, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0x00, 0xa0, 3}, { 1500000, 25000, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xa1, 0xed, 3}, { 3400000, 0, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xee, 0xff, 3}, /* buck 6 */ { 500000, 6250, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0x00, 0xa0, 3}, { 1500000, 25000, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xa1, 0xed, 3}, { 3400000, 0, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xee, 0xff, 3}, /* buck 7 */ { 500000, 6250, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0x00, 0xa0, 3}, { 1500000, 25000, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xa1, 0xed, 3}, { 3400000, 0, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xee, 0xff, 3}, /* buck 8 */ { 500000, 6250, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0x00, 0xa0, 3}, { 1500000, 25000, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xa1, 0xed, 3}, { 3400000, 0, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xee, 0xff, 3}, /* buck 9 */ { 500000, 6250, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0x00, 0xa0, 3}, { 1500000, 25000, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xa1, 0xed, 3}, { 3400000, 0, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xee, 0xff, 3}, /* buck 10 */ { 500000, 6250, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0x00, 0xa0, 3}, { 1500000, 25000, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xa1, 0xed, 3}, { 3400000, 0, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xee, 0xff, 3}, }; static const struct rk8xx_reg_info rk806_nldo[] = { /* nldo1 */ { 500000, 12500, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, /* nldo2 */ { 500000, 12500, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, /* nldo3 */ { 500000, 12500, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, /* nldo4 */ { 500000, 12500, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, /* nldo5 */ { 500000, 12500, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, }; static const struct rk8xx_reg_info rk806_pldo[] = { /* pldo1 */ { 500000, 12500, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, /* pldo2 */ { 500000, 12500, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, /* pldo3 */ { 500000, 12500, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, /* pldo4 */ { 500000, 12500, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, /* pldo5 */ { 500000, 12500, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, /* pldo6 */ { 500000, 12500, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0x00, }, { 3400000, 0, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, }; #if 0 static void io_mem_show(const char *label, unsigned long base, unsigned int start, unsigned int end) { unsigned int val, offset = start, nr = 0; if (label) DEBUG ((DEBUG_ERROR, "%a:\n", label)); DEBUG ((DEBUG_ERROR, "%08lx: ", base + offset)); for (offset = start; offset <= end; offset += 0x04) { if (nr >= 4) { DEBUG ((DEBUG_ERROR, "\n%08lx: ", base + offset)); nr = 0; } val = MmioRead32(base + offset); DEBUG ((DEBUG_ERROR, "%08lx ", val)); nr++; } DEBUG ((DEBUG_ERROR, "\n")); } #endif static RETURN_STATUS _spi_read(INT32 cs_id, UINT32 reg, UINT8 *buffer, INT32 len) { UINT8 txbuf[8]; RETURN_STATUS status; txbuf[0] = RK806_CMD_READ; txbuf[1] = reg; txbuf[2] = RK806_REG_H; SPI_SetCS(&gSPI, cs_id, 1); status = SPI_Configure(&gSPI, txbuf, NULL, 3); status = SPI_PioTransfer(&gSPI); SPI_Stop(&gSPI); status = SPI_Configure(&gSPI, NULL, buffer, 1); status = SPI_PioTransfer(&gSPI); SPI_Stop(&gSPI); SPI_SetCS(&gSPI, cs_id, 0); return status; } static RETURN_STATUS _spi_write(INT32 cs_id, UINT32 reg, const UINT8 *buffer, INT32 len) { UINT8 txbuf[4]; RETURN_STATUS status; txbuf[0] = RK806_CMD_WRITE; txbuf[1] = reg; txbuf[2] = RK806_REG_H; txbuf[3] = *buffer; SPI_SetCS(&gSPI, cs_id, 1); status = SPI_Configure(&gSPI, txbuf, NULL, 4); status = SPI_PioTransfer(&gSPI); SPI_Stop(&gSPI); SPI_SetCS(&gSPI, cs_id, 0); return status; } static RETURN_STATUS pmic_reg_read(INT32 cs_id, UINT32 reg, UINT8 *buffer, INT32 len) { RETURN_STATUS ret; ret = _spi_read(cs_id, reg, buffer, len); if (ret) DEBUG ((RK806_DBG, "cs_id %d rk806 read reg(0x%x) error: %d buffer = %x\n", cs_id, reg, ret, buffer[0])); return ret; } static INT32 pmic_reg_write(INT32 cs_id, UINT32 reg, const UINT8 *buffer, INT32 len) { RETURN_STATUS ret; ret = _spi_write(cs_id, reg, buffer, len); if (ret) DEBUG ((RK806_DBG, "cs_id %d rk806 write reg(0x%x) error: %d %x\n", cs_id, reg, ret, buffer[0])); return ret; } static RETURN_STATUS pmic_clrsetbits(INT32 cs_id, UINT32 reg, UINT32 clr, UINT32 set) { UINT8 byte; RETURN_STATUS ret; ret = pmic_reg_read(cs_id, reg, &byte, 0x01); if (ret < 0) return ret; byte = (ret & ~clr) | set; pmic_reg_write(cs_id, reg, &byte, 1); ret = pmic_reg_read(cs_id, reg, &byte, 0x01); return ret; } static const struct rk8xx_reg_info *get_buck_reg(INT32 num, INT32 uvolt) { if (uvolt < 1500000) return &rk806_buck[num * 3 + 0]; else if (uvolt < 3400000) return &rk806_buck[num * 3 + 1]; else return &rk806_buck[num * 3 + 2]; } static const struct rk8xx_reg_info *get_nldo_reg(INT32 num, INT32 uvolt) { if (uvolt < 3400000) return &rk806_nldo[num * 2]; else return &rk806_nldo[num * 2 + 1]; } static const struct rk8xx_reg_info *get_pldo_reg(INT32 num, INT32 uvolt) { if (uvolt < 3400000) return &rk806_pldo[num * 2]; else return &rk806_pldo[num * 2 + 1]; } static RETURN_STATUS buck_set_voltage(INT32 reg_id, INT32 uvolt) { INT32 buck = reg_id & 0x0f; const struct rk8xx_reg_info *info = get_buck_reg(buck, uvolt); INT32 mask = info->vsel_mask; INT32 cs_id = (reg_id & 0xf00) >> 8; INT32 val; if (info->vsel_reg == NA) return RETURN_INVALID_PARAMETER; if (info->step_uv == 0) /* Fixed voltage */ val = info->min_sel; else val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; DEBUG ((RK806_DBG, "%a: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n", __func__, uvolt, buck + 1, info->vsel_reg, mask, val)); return pmic_clrsetbits(cs_id, info->vsel_reg, mask, val); } static RETURN_STATUS nldo_set_voltage(INT32 reg_id, INT32 uvolt) { INT32 ldo = reg_id & 0x0f; const struct rk8xx_reg_info *info = get_nldo_reg(ldo, uvolt); INT32 mask = info->vsel_mask; INT32 cs_id = (reg_id & 0xf00) >> 8; INT32 val; if (info->vsel_reg == NA) return RETURN_INVALID_PARAMETER; if (info->step_uv == 0) val = info->min_sel; else val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; DEBUG ((RK806_DBG, "%a: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", __func__, uvolt, ldo + 1, info->vsel_reg, mask, val)); return pmic_clrsetbits(cs_id, info->vsel_reg, mask, val); } static RETURN_STATUS pldo_set_voltage(INT32 reg_id, INT32 uvolt) { INT32 ldo = reg_id & 0x0f; const struct rk8xx_reg_info *info = get_pldo_reg(ldo, uvolt); INT32 mask = info->vsel_mask; INT32 cs_id = (reg_id & 0xf00) >> 8; INT32 val; if (info->vsel_reg == NA) return RETURN_INVALID_PARAMETER; if (info->step_uv == 0) val = info->min_sel; else val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; DEBUG ((RK806_DBG, "%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", __func__, uvolt, ldo + 1, info->vsel_reg, mask, val)); return pmic_clrsetbits(cs_id, info->vsel_reg, mask, val); } static RETURN_STATUS buck_set_enable(INT32 reg_id, BOOLEAN enable) { INT32 cs_id = (reg_id & 0xf00) >> 8; INT32 buck = reg_id & 0x0f; UINT8 value, en_reg; RETURN_STATUS ret; en_reg = RK806_POWER_EN(buck / 4); if (enable) value = ((1 << buck % 4) | (1 << (buck % 4 + 4))); else value = ((0 << buck % 4) | (1 << (buck % 4 + 4))); ret = pmic_reg_write(cs_id, en_reg, &value, 1); return ret; } static RETURN_STATUS nldo_set_enable(INT32 reg_id, BOOLEAN enable) { INT32 cs_id = (reg_id & 0xf00) >> 8; INT32 ldo = reg_id & 0x0f; UINT8 value, en_reg; RETURN_STATUS ret; if (ldo < 4) { en_reg = RK806_NLDO_EN(0); if (enable) value = ((1 << ldo % 4) | (1 << (ldo % 4 + 4))); else value = ((0 << ldo % 4) | (1 << (ldo % 4 + 4))); ret = pmic_reg_write(cs_id, en_reg, &value, 1); } else { en_reg = RK806_NLDO_EN(2); if (enable) value = 0x44; else value = 0x40; ret = pmic_reg_write(cs_id, en_reg, &value, 1); } return ret; } static RETURN_STATUS pldo_set_enable(INT32 reg_id, BOOLEAN enable) { INT32 cs_id = (reg_id & 0xf00) >> 8; INT32 pldo = reg_id & 0x0f; UINT8 value, en_reg; RETURN_STATUS ret; if (pldo < 3) { en_reg = RK806_PLDO_EN(0); if (enable) value = RK806_PLDO0_2_SET(pldo); else value = RK806_PLDO0_2_CLR(pldo); ret = pmic_reg_write(cs_id, en_reg, &value, 1); } else if (pldo == 3) { en_reg = RK806_PLDO_EN(1); if (enable) { value = ((1 << 0) | (1 << 4)); } else { value = (1 << 4); } ret = pmic_reg_write(cs_id, en_reg, &value, 1); } else if (pldo == 4) { en_reg = RK806_PLDO_EN(1); if (enable) value = ((1 << 1) | (1 << 5)); else value = ((0 << 1) | (1 << 5)); ret = pmic_reg_write(cs_id, en_reg, &value, 1); } else if (pldo == 5) { en_reg = RK806_PLDO_EN(0); if (enable) value = ((1 << 0) | (1 << 4)); else value = ((0 << 0) | (1 << 4)); ret = pmic_reg_write(cs_id, en_reg, &value, 1); } return ret; } void RK806RegulatorInit(struct regulator_init_data init_data) { INT32 reg_id; INT32 init_voltage; init_voltage = init_data.init_voltage_mv; reg_id = init_data.reg_id; if ((reg_id & 0xf0) == BUCK) { buck_set_voltage(reg_id, init_voltage); buck_set_enable(reg_id, 1); } else if ((reg_id & 0xf0) == NLDO) { nldo_set_voltage(reg_id, init_voltage); nldo_set_enable(reg_id, 1); } if ((reg_id & 0xf0) == PLDO) { pldo_set_voltage(reg_id, init_voltage); pldo_set_enable(reg_id, 1); } } static RETURN_STATUS SpiCongig(struct SPI_HANDLE *pSPI) { struct SPI_CONFIG *pSPIConfig = &pSPI->config; DEBUG ((DEBUG_ERROR, "%a(%u): 0: %x\n", "SpiCongig", __LINE__, 0)); /* Data width */ pSPIConfig->nBytes = CR0_DATA_FRAME_SIZE_8BIT; /* CPOL */ //pSPIConfig->clkPolarity = CR0_POLARITY_HIGH; pSPIConfig->clkPolarity = CR0_POLARITY_LOW; /* CPHA */ //pSPIConfig->clkPhase = CR0_PHASE_2EDGE; pSPIConfig->clkPhase = CR0_PHASE_1EDGE; /* MSB or LSB */ pSPIConfig->firstBit = CR0_FIRSTBIT_MSB; //pSPIConfig->firstBit = CR0_FIRSTBIT_LSB; /* Master or Slave */ //pSPIConfig->opMode = CR0_OPM_SLAVE; pSPIConfig->opMode = CR0_OPM_MASTER; /* CSM cycles */ pSPIConfig->csm = 0; pSPI->maxFreq = 24000000; pSPIConfig->speed = 2000000; if (pSPI->config.speed > HAL_SPI_MASTER_MAX_SCLK_OUT) { pSPI->config.speed = HAL_SPI_MASTER_MAX_SCLK_OUT; } return RETURN_SUCCESS; } RETURN_STATUS RK806Init(void) { UINT32 base = FixedPcdGet32 (SpiRK806BaseAddr); Rk806SpiIomux(); DEBUG ((DEBUG_ERROR, "%a(%u): base: %x\n", "RK806Init", __LINE__, base)); SPI_Init(&gSPI, base); SpiCongig(&gSPI); return RETURN_SUCCESS; }