| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- /**************************************************************************//**
- *
- * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-11-11 Wayne First version
- *
- ******************************************************************************/
- #include <rtthread.h>
- #include "NuMicro.h"
- #define ERROR rt_kprintf
- #define RETRY_COUNT 3
- /*---------------------------------------------------------------------------------------------------------*/
- /* Global variables */
- /*---------------------------------------------------------------------------------------------------------*/
- static uint8_t g_u8DeviceAddr = 0xB0;
- static uint8_t g_uPageNum;
- static uint8_t g_u8RegAddr;
- static uint8_t g_u8WriteData;
- static volatile uint8_t g_u8RxData;
- static volatile uint8_t g_u8DataLen;
- static volatile uint8_t g_u8EndFlag = 0;
- static void I2C0_MasterRx(uint32_t u32Status)
- {
- if (u32Status == 0x08)
- {
- /* START has been transmitted and prepare SLA+W */
- I2C0->DAT = g_u8DeviceAddr | (g_uPageNum << 1);
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | I2C_CTL_SI;
- }
- else if (u32Status == 0x18)
- {
- /* SLA+W has been transmitted and ACK has been received */
- I2C0->DAT = g_u8RegAddr;
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | I2C_CTL_SI;
- }
- else if (u32Status == 0x20)
- {
- /* SLA+W has been transmitted and NACK has been received */
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | (I2C_CTL_STA | I2C_CTL_STO | I2C_CTL_SI);
- }
- else if (u32Status == 0x28)
- {
- /* DATA has been transmitted and ACK has been received */
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | (I2C_CTL_STA | I2C_CTL_SI); // repeat start
- }
- else if (u32Status == 0x10)
- {
- /* Repeat START has been transmitted and prepare SLA+R */
- I2C0->DAT = (g_u8DeviceAddr | (g_uPageNum << 1)) | 0x01;
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | I2C_CTL_SI;
- }
- else if (u32Status == 0x40)
- {
- /* SLA+R has been transmitted and ACK has been received */
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | I2C_CTL_SI;
- }
- else if (u32Status == 0x58)
- {
- /* DATA has been received and NACK has been returned */
- g_u8RxData = I2C0->DAT;
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | (I2C_CTL_STO | I2C_CTL_SI);
- g_u8EndFlag = 1;
- }
- else
- {
- ERROR("Status 0x%x is NOT processed\n", u32Status);
- }
- }
- static void I2C0_MasterTx(uint32_t u32Status)
- {
- if (u32Status == 0x08)
- {
- /* START has been transmitted */
- I2C0->DAT = g_u8DeviceAddr | (g_uPageNum << 1); /* Write SLA+W to Register I2CDAT */
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | I2C_CTL_SI;
- }
- else if (u32Status == 0x18)
- {
- /* SLA+W has been transmitted and ACK has been received */
- I2C0->DAT = g_u8RegAddr;
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | I2C_CTL_SI;
- }
- else if (u32Status == 0x20)
- {
- /* SLA+W has been transmitted and NACK has been received */
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | (I2C_CTL_STA | I2C_CTL_STO | I2C_CTL_SI);
- }
- else if (u32Status == 0x28)
- {
- /* DATA has been transmitted and ACK has been received */
- if ((g_u8DataLen == 0) && (g_u8EndFlag == 0))
- {
- I2C0->DAT = g_u8WriteData;
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | I2C_CTL_SI;
- g_u8DataLen++;
- }
- else
- {
- g_u8DataLen = 0;
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | (I2C_CTL_STO | I2C_CTL_SI);
- g_u8EndFlag = 1;
- }
- }
- else
- {
- ERROR("Status 0x%x is NOT processed\n", u32Status);
- }
- }
- static uint32_t ma35d1_write_i2c_data(uint32_t u32Addr, uint32_t u32Data)
- {
- uint32_t I2C_TIME_OUT_COUNT = 0x20000;
- uint32_t u32Status;
- uint32_t u32time_out = 0;
- g_uPageNum = 0;
- if (g_uPageNum == 0xff)
- {
- ERROR("\n address error !!\n");
- return 0;
- }
- g_u8RegAddr = u32Addr;
- g_u8WriteData = u32Data;
- g_u8EndFlag = 0x0;
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | I2C_CTL_STA;
- while (1)
- {
- if (I2C0->CTL0 & I2C_CTL_SI)
- {
- u32time_out = 0;
- u32Status = I2C0->STATUS0;
- I2C0_MasterTx(u32Status);
- }
- if (g_u8EndFlag)
- {
- break;
- }
- u32time_out++;
- if (u32time_out > I2C_TIME_OUT_COUNT)
- {
- ERROR("i2c Write Time Out!\n");
- return 0; // error
- }
- }
- return 1;
- }
- static uint32_t ma35d1_read_i2c_data(uint32_t u32Addr, uint32_t *pu32Data)
- {
- uint32_t I2C_TIME_OUT_COUNT = 0x200000;
- uint32_t u32Status;
- uint32_t u32time_out = 0;
- g_uPageNum = 0;
- if (g_uPageNum == 0xff)
- {
- ERROR("\n address error !!\n");
- return 0;
- }
- g_u8RegAddr = u32Addr;
- g_u8EndFlag = 0x0;
- I2C0->CTL0 = (I2C0->CTL0 & ~0x3c) | I2C_CTL_STA;
- while (1)
- {
- if (I2C0->CTL0 & I2C_CTL_SI)
- {
- u32time_out = 0;
- u32Status = I2C0->STATUS0;
- I2C0_MasterRx(u32Status);
- }
- if (g_u8EndFlag)
- {
- break;
- }
- u32time_out++;
- if (u32time_out > I2C_TIME_OUT_COUNT)
- {
- ERROR("i2c Read Time Out!\n");
- return 1; // error
- }
- }
- *pu32Data = g_u8RxData;
- return 2;
- }
- static uint32_t ma35d1_read_pmic_data(uint32_t u32Addr, uint32_t *pu32Data)
- {
- uint32_t j = RETRY_COUNT;
- while (j-- > 0)
- {
- if (ma35d1_read_i2c_data(u32Addr, pu32Data) == 2)
- {
- break;
- }
- }
- if (j <= 0)
- {
- ERROR("\n READ ERROR! \n");
- return 0;
- }
- return 1;
- }
- static uint32_t ma35d1_write_pmic_data(uint32_t u32Addr, uint32_t u32Data)
- {
- uint32_t j = RETRY_COUNT;
- while (j-- > 0)
- {
- if (ma35d1_write_i2c_data(u32Addr, u32Data) == 1)
- {
- break;
- }
- }
- if (j <= 0)
- {
- ERROR("\n WRITE ERROR [%d]! \n", j);
- return 0;
- }
- return 1;
- }
- static void ma35d1_i2c0_init(uint32_t sys_clk)
- {
- unsigned long clk_rate;
- uint32_t u32Div, speed;
- outpw((void *)0x40460208, inpw((void *)0x40460208) | (0x3fff << 16)); // enable GPIO clock
- outpw((void *)0x40460210, inpw((void *)0x40460210) | (0x1 << 0)); // I2C0 CLK
- outpw(0x40460098, ((inpw(0x40460098) & ~0x0f000000) | (0x6 << 24))); // PD.6 I2C0_SDA
- outpw(0x40460098, ((inpw(0x40460098) & ~0xf0000000) | (0x6 << 28))); // PD.7 I2C0_CLK
- outpw(0x400400F0, 0x5 << 12); // pull high
- /* i2c_clk = 100KHz */
- clk_rate = sys_clk;
- speed = 100 * 1000;
- /* assume speed above 1000 are Hz-specified */
- if (speed > 1000) speed = speed / 1000;
- if (speed > 400) speed = 400;
- u32Div = (uint32_t)(((clk_rate * 10U) / (speed * 4U) + 5U) / 10U - 1U);
- I2C0->CLKDIV = u32Div;
- I2C0->CTL0 = I2C0->CTL0 | I2C_CTL0_I2CEN_Msk; /* i2c enable */
- }
- uint32_t ma35d1_set_cpu_voltage(uint32_t sys_clk, uint32_t u32Vol)
- {
- /*
- RegValue = (Voltage - 0.3) / 0.01
- RegValue(hex) Voltage(v)
- 0x5B 1.22
- 0x5C 1.23
- 0x5D 1.24
- 0x5F 1.25
- 0x60 1.26
- 0x61 1.27
- 0x62 1.28
- 0x63 1.29
- 0x64 1.30
- 0x65 1.31
- 0x66 1.32
- 0x67 1.33
- 0x68 1.34
- 0x69 1.35
- */
- uint32_t u32Data = 0;
- if ((u32Vol < 0x59) || (u32Vol > 0x68))
- return 0;
- ma35d1_i2c0_init(sys_clk);
- ma35d1_write_pmic_data(0xA4, u32Vol);
- ma35d1_read_pmic_data(0xA4, &u32Data);
- return (u32Data == u32Vol);
- }
|