mirror of
https://github.com/ivoszbg/uniLoader.git
synced 2024-12-03 09:20:08 +00:00
drivers: samsung: Introduce exynos-speedy
Speedy is a serial communication bus that is typically used in Exynos SoC devices for communicating with a PMIC. Implement basic support for it, as well as add its first user - s2mps17 in board-dreamlte. Also, while at it, implement a simple readl function. Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
This commit is contained in:
parent
8b562d28fa
commit
eba7aec49d
@ -3,11 +3,20 @@
|
||||
* Copyright (c) 2022, Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
|
||||
*/
|
||||
#include <board.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <drivers/framework.h>
|
||||
#include <lib/simplefb.h>
|
||||
#include <lib/debug.h>
|
||||
#include <soc/exynos8895.h>
|
||||
#include <drivers/samsung/exynos-speedy.h>
|
||||
|
||||
#define DECON_F_BASE 0x12860000
|
||||
#define HW_SW_TRIG_CONTROL 0x70
|
||||
/* DECON Register MAP */
|
||||
#define HW_SW_TRIG_CONTROL 0x70
|
||||
|
||||
/* MMIO MAP */
|
||||
#define DECON_F_BASE 0x12860000
|
||||
#define SPEEDY_BASE 0x15b50000
|
||||
|
||||
void init_board_funcs(void *board)
|
||||
{
|
||||
@ -23,6 +32,94 @@ void init_board_funcs(void *board)
|
||||
board_restruct->name = "DREAMLTE";
|
||||
}
|
||||
|
||||
enum s2mps17_ldos {
|
||||
S2MPS17_LDO2,
|
||||
S2MPS17_LDO34,
|
||||
S2MPS17_LDO35,
|
||||
S2MPS17_END
|
||||
};
|
||||
|
||||
struct s2mps17_data {
|
||||
uint8_t ldo_ctrl_value;
|
||||
uint32_t ldo_voltage_value;
|
||||
};
|
||||
|
||||
/* Slave addr = 0xCC */
|
||||
/* S2MPS17 Register MAP */
|
||||
#define S2MPS17_PMIC_REG_L2CTRL 0x3e
|
||||
#define S2MPS17_PMIC_REG_L34CTRL 0x5f
|
||||
#define S2MPS17_PMIC_REG_L35CTRL 0x60
|
||||
|
||||
#define S2MPS17_BUCK_MIN1 300000
|
||||
#define S2MPS17_BUCK_MIN2 600000
|
||||
#define S2MPS17_LDO_MIN1 700000
|
||||
#define S2MPS17_LDO_MIN2 400000
|
||||
#define S2MPS17_LDO_MIN3 1800000
|
||||
#define S2MPS17_LDO_MIN4 300000
|
||||
|
||||
#define S2MPS17_LDO_STEP1 12500
|
||||
#define S2MPS17_LDO_STEP2 25000
|
||||
|
||||
#define S2MPS17_LDO_VSEL_MASK 0x3f
|
||||
#define S2MPS17_BUCK_VSEL_MASK 0xff
|
||||
|
||||
#define S2MPS17_ENABLE_MASK (3 << 6)
|
||||
|
||||
#define S2MPS17_LDO2_VOLTAGE 2800000
|
||||
#define S2MPS17_LDO34_VOLTAGE 1850000
|
||||
#define S2MPS17_LDO35_VOLTAGE 3000000
|
||||
|
||||
#define _LDO(macro) S2MPS17_LDO##macro
|
||||
#define _REG(ctrl) S2MPS17_PMIC_REG##ctrl
|
||||
#define _ldo_ops(num) s2mps17_ldo_ops##num
|
||||
#define _TIME(macro) S2MPS17_ENABLE_TIME##macro
|
||||
|
||||
static void s2mps17_setup(void)
|
||||
{
|
||||
int ret;
|
||||
struct speedy_transaction s2mps17;
|
||||
|
||||
/* S2MPS17 configuration */
|
||||
s2mps17.base = SPEEDY_BASE;
|
||||
s2mps17.slave = 1;
|
||||
|
||||
/*
|
||||
* Define LDO control register values
|
||||
* Calculation formula: enable mask + (voltage to set - minimal voltage) / step value
|
||||
*/
|
||||
const struct s2mps17_data data[] = {
|
||||
{
|
||||
S2MPS17_PMIC_REG_L2CTRL, // vqmmc
|
||||
S2MPS17_ENABLE_MASK + (S2MPS17_LDO2_VOLTAGE -
|
||||
S2MPS17_LDO_MIN3) / S2MPS17_LDO_STEP2
|
||||
}, {
|
||||
S2MPS17_PMIC_REG_L34CTRL, // tsp_io
|
||||
S2MPS17_ENABLE_MASK + (S2MPS17_LDO34_VOLTAGE -
|
||||
S2MPS17_LDO_MIN1) / S2MPS17_LDO_STEP2
|
||||
}, {
|
||||
S2MPS17_PMIC_REG_L35CTRL, // tsp_avdd
|
||||
S2MPS17_ENABLE_MASK + (S2MPS17_LDO35_VOLTAGE -
|
||||
S2MPS17_LDO_MIN3) / S2MPS17_LDO_STEP2
|
||||
}
|
||||
};
|
||||
|
||||
/* Go ahead and enable the LDOs */
|
||||
for (int i = 0; i < S2MPS17_END; i++) {
|
||||
s2mps17.offset = data[i].ldo_ctrl_value;
|
||||
s2mps17.val = data[i].ldo_voltage_value;
|
||||
|
||||
ret = speedy_write(&s2mps17);
|
||||
if (ret)
|
||||
goto handle_err;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
handle_err:
|
||||
printk(KERN_ERR, "s2mps17: err\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Early initialization
|
||||
int board_init(void)
|
||||
{
|
||||
@ -34,6 +131,8 @@ int board_init(void)
|
||||
// Late initialization
|
||||
int board_late_init(void)
|
||||
{
|
||||
s2mps17_setup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,2 +1,3 @@
|
||||
# the drivers registration framework
|
||||
lib-y += framework.o
|
||||
lib-y += samsung/exynos-speedy.o
|
||||
|
196
drivers/samsung/exynos-speedy.c
Normal file
196
drivers/samsung/exynos-speedy.c
Normal file
@ -0,0 +1,196 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2024, Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
|
||||
* Copyright (c) 2024 Markuss Broks <markuss.broks@gmail.com>
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <drivers/framework.h>
|
||||
#include <drivers/samsung/exynos-speedy.h>
|
||||
|
||||
/* SPEEDY Register MAP */
|
||||
#define SPEEDY_CTRL 0x000
|
||||
#define SPEEDY_FIFO_CTRL 0x004
|
||||
#define SPEEDY_CMD 0x008
|
||||
#define SPEEDY_INT_ENABLE 0x00c
|
||||
#define SPEEDY_INT_STATUS 0x010
|
||||
#define SPEEDY_FIFO_STATUS 0x030
|
||||
#define SPEEDY_TX_DATA 0x034
|
||||
#define SPEEDY_RX_DATA 0x038
|
||||
#define SPEEDY_PACKET_GAP_TIME 0x044
|
||||
#define SPEEDY_TIMEOUT_COUNT 0x048
|
||||
#define SPEEDY_FIFO_DEBUG 0x100
|
||||
#define SPEEDY_CTRL_STATUS 0x104
|
||||
|
||||
/* SPEEDY_CTRL Register bits */
|
||||
#define SPEEDY_ENABLE (1 << 0)
|
||||
#define SPEEDY_TIMEOUT_CMD_DISABLE (1 << 1)
|
||||
#define SPEEDY_TIMEOUT_STANDBY_DISABLE (1 << 2)
|
||||
#define SPEEDY_TIMEOUT_DATA_DISABLE (1 << 3)
|
||||
#define SPEEDY_ALWAYS_PULLUP_EN (1 << 7)
|
||||
#define SPEEDY_DATA_WIDTH_8BIT (0 << 8)
|
||||
#define SPEEDY_REMOTE_RESET_REQ (1 << 30)
|
||||
#define SPEEDY_SW_RST (1 << 31)
|
||||
|
||||
/* SPEEDY_FIFO_CTRL Register bits */
|
||||
#define SPEEDY_RX_TRIGGER_LEVEL(x) ((x) << 0)
|
||||
#define SPEEDY_TX_TRIGGER_LEVEL(x) ((x) << 8)
|
||||
#define SPEEDY_FIFO_DEBUG_INDEX (0 << 24)
|
||||
#define SPEEDY_FIFO_RESET (1 << 31)
|
||||
|
||||
/* SPEEDY_CMD Register bits */
|
||||
#define SPEEDY_BURST_LENGTH(x) ((x) << 0)
|
||||
#define SPEEDY_BURST_FIXED (0 << 5)
|
||||
#define SPEEDY_BURST_INCR (1 << 5)
|
||||
#define SPEEDY_BURST_EXTENSION (2 << 5)
|
||||
#define SPEEDY_ACCESS_BURST (0 << 19)
|
||||
#define SPEEDY_ACCESS_RANDOM (1 << 19)
|
||||
#define SPEEDY_DIRECTION_READ (0 << 20)
|
||||
#define SPEEDY_DIRECTION_WRITE (1 << 20)
|
||||
|
||||
/* SPEEDY_INT_ENABLE Register bits */
|
||||
#define SPEEDY_TRANSFER_DONE_EN (1 << 0)
|
||||
#define SPEEDY_TIMEOUT_CMD_EN (1 << 1)
|
||||
#define SPEEDY_TIMEOUT_STANDBY_EN (1 << 2)
|
||||
#define SPEEDY_TIMEOUT_DATA_EN (1 << 3)
|
||||
#define SPEEDY_FIFO_RX_ALMOST_FULL_EN (1 << 8)
|
||||
#define SPEEDY_FIFO_TX_ALMOST_EMPTY_EN (1 << 4)
|
||||
#define SPEEDY_RX_FIFO_INT_TRAILER_EN (1 << 9)
|
||||
#define SPEEDY_RX_MODEBIT_ERR_EN (1 << 16)
|
||||
#define SPEEDY_RX_GLITCH_ERR_EN (1 << 17)
|
||||
#define SPEEDY_RX_ENDBIT_ERR_EN (1 << 18)
|
||||
#define SPEEDY_TX_LINE_BUSY_ERR_EN (1 << 20)
|
||||
#define SPEEDY_TX_STOPBIT_ERR_EN (1 << 21)
|
||||
#define SPEEDY_REMOTE_RESET_REQ_EN (1 << 31)
|
||||
|
||||
/* SPEEDY_INT_STATUS Register bits */
|
||||
#define SPEEDY_TRANSFER_DONE (1 << 0)
|
||||
#define SPEEDY_TIMEOUT_CMD (1 << 1)
|
||||
#define SPEEDY_TIMEOUT_STANDBY (1 << 2)
|
||||
#define SPEEDY_TIMEOUT_DATA (1 << 3)
|
||||
#define SPEEDY_FIFO_TX_ALMOST_EMPTY (1 << 4)
|
||||
#define SPEEDY_FIFO_RX_ALMOST_FULL (1 << 8)
|
||||
#define SPEEDY_RX_FIFO_INT_TRAILER (1 << 9)
|
||||
#define SPEEDY_RX_MODEBIT_ERR (1 << 16)
|
||||
#define SPEEDY_RX_GLITCH_ERR (1 << 17)
|
||||
#define SPEEDY_RX_ENDBIT_ERR (1 << 18)
|
||||
#define SPEEDY_TX_LINE_BUSY_ERR (1 << 20)
|
||||
#define SPEEDY_TX_STOPBIT_ERR (1 << 21)
|
||||
#define SPEEDY_REMOTE_RESET_REQ_STAT (1 << 31)
|
||||
|
||||
/* SPEEDY_FIFO_STATUS Register bits */
|
||||
#define SPEEDY_VALID_DATA_CNT (0 << 0)
|
||||
#define SPEEDY_FIFO_FULL (1 << 5)
|
||||
#define SPEEDY_FIFO_EMPTY (1 << 6)
|
||||
|
||||
/* SPEEDY_PACKET_GAP_TIME Register bits */
|
||||
#define SPEEDY_FIFO_TX_ALMOST_EMPTY (1 << 4)
|
||||
#define SPEEDY_FSM_INIT (1 << 1)
|
||||
#define SPEEDY_FSM_TX_CMD (1 << 2)
|
||||
#define SPEEDY_FSM_STANDBY (1 << 3)
|
||||
#define SPEEDY_FSM_DATA (1 << 4)
|
||||
#define SPEEDY_FSM_TIMEOUT (1 << 5)
|
||||
#define SPEEDY_FSM_TRANS_DONE (1 << 6)
|
||||
#define SPEEDY_FSM_IO_RX_STAT_MASK (3 << 7)
|
||||
#define SPEEDY_FSM_IO_TX_IDLE (1 << 9)
|
||||
#define SPEEDY_FSM_IO_TX_GET_PACKET (1 << 10)
|
||||
#define SPEEDY_FSM_IO_TX_PACKET (1 << 11)
|
||||
#define SPEEDY_FSM_IO_TX_DONE (1 << 12)
|
||||
|
||||
#define SPEEDY_RX_LENGTH(n) ((n) << 0)
|
||||
#define SPEEDY_TX_LENGTH(n) ((n) << 8)
|
||||
|
||||
#define SPEEDY_SLAVE(x) ((x & 0xf) << 15)
|
||||
#define SPEEDY_ADDRESS(x) ((x & 0xff) << 7)
|
||||
|
||||
static int speedy_fifo_reset(unsigned long base)
|
||||
{
|
||||
writel(SPEEDY_FIFO_RESET, (void *)(base + SPEEDY_FIFO_CTRL));
|
||||
/* TODO: Implement a proper delay func */
|
||||
for (volatile int i = 0; i < 1000; i++);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int speedy_int_clear(unsigned long base)
|
||||
{
|
||||
writel(0xFFFFFFFF, (void *)(base + SPEEDY_INT_STATUS));
|
||||
/* TODO: Implement a proper delay func */
|
||||
for (volatile int i = 0; i < 1000; i++);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int speedy_read(struct speedy_transaction *tr)
|
||||
{
|
||||
int ret = speedy_fifo_reset(tr->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
writel(SPEEDY_RX_LENGTH(1) | SPEEDY_TX_LENGTH(1),
|
||||
(void *)(tr->base + SPEEDY_FIFO_CTRL));
|
||||
|
||||
unsigned int cmd = SPEEDY_ACCESS_RANDOM | SPEEDY_DIRECTION_READ |
|
||||
SPEEDY_SLAVE(tr->slave) | SPEEDY_ADDRESS(tr->offset);
|
||||
|
||||
writel(SPEEDY_TRANSFER_DONE | SPEEDY_FIFO_RX_ALMOST_FULL_EN |
|
||||
SPEEDY_RX_FIFO_INT_TRAILER_EN | SPEEDY_RX_MODEBIT_ERR_EN |
|
||||
SPEEDY_RX_GLITCH_ERR_EN | SPEEDY_RX_ENDBIT_ERR_EN |
|
||||
SPEEDY_REMOTE_RESET_REQ_EN,
|
||||
(void *)(tr->base + SPEEDY_INT_ENABLE));
|
||||
|
||||
speedy_int_clear(tr->base);
|
||||
|
||||
writel(cmd, (void *)(tr->base + SPEEDY_CMD));
|
||||
|
||||
// Poll for completion
|
||||
int timeout = 500000;
|
||||
while (timeout-- > 0) {
|
||||
unsigned int int_status;
|
||||
int_status = readl((volatile uint32_t *)(tr->base +
|
||||
SPEEDY_INT_STATUS));
|
||||
if (int_status & SPEEDY_TRANSFER_DONE) {
|
||||
speedy_int_clear(tr->base);
|
||||
tr->val = readl((volatile uint32_t *)
|
||||
(tr->base + SPEEDY_RX_DATA));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int speedy_write(struct speedy_transaction *tr)
|
||||
{
|
||||
int ret = speedy_fifo_reset(tr->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
writel(SPEEDY_RX_LENGTH(1) | SPEEDY_TX_LENGTH(1),
|
||||
(void *)(tr->base + SPEEDY_FIFO_CTRL));
|
||||
|
||||
unsigned int cmd = SPEEDY_ACCESS_RANDOM | SPEEDY_DIRECTION_WRITE |
|
||||
SPEEDY_SLAVE(tr->slave) | SPEEDY_ADDRESS(tr->offset);
|
||||
|
||||
writel(SPEEDY_TRANSFER_DONE_EN | SPEEDY_FIFO_TX_ALMOST_EMPTY_EN |
|
||||
SPEEDY_TX_LINE_BUSY_ERR_EN | SPEEDY_TX_STOPBIT_ERR_EN |
|
||||
SPEEDY_REMOTE_RESET_REQ_EN,
|
||||
(void *)(tr->base + SPEEDY_INT_ENABLE));
|
||||
|
||||
speedy_int_clear(tr->base);
|
||||
|
||||
writel(cmd, (void *)(tr->base + SPEEDY_CMD));
|
||||
writel(tr->val, (void *)(tr->base + SPEEDY_TX_DATA));
|
||||
|
||||
// Poll for completion
|
||||
int timeout = 500000;
|
||||
while (timeout-- > 0) {
|
||||
unsigned int int_status;
|
||||
int_status = readl((volatile uint32_t *)(tr->base +
|
||||
SPEEDY_INT_STATUS));
|
||||
if (int_status & SPEEDY_TRANSFER_DONE) {
|
||||
speedy_int_clear(tr->base);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
22
include/drivers/samsung/exynos-speedy.h
Normal file
22
include/drivers/samsung/exynos-speedy.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||
/*
|
||||
* Copyright (c) 2024 Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
|
||||
* Copyright (c) 2024 Markuss Broks <markuss.broks@gmail.com>
|
||||
*
|
||||
* Bindings for exynos-speedy
|
||||
*/
|
||||
|
||||
#ifndef EXYNOS_SPEEDY_H_
|
||||
#define EXYNOS_SPEEDY_H_
|
||||
|
||||
struct speedy_transaction {
|
||||
unsigned long base;
|
||||
unsigned int slave;
|
||||
unsigned int offset;
|
||||
unsigned int val;
|
||||
};
|
||||
|
||||
extern int speedy_read(struct speedy_transaction *tr);
|
||||
extern int speedy_write(struct speedy_transaction *tr);
|
||||
|
||||
#endif /* EXYNOS_SPEEDY_H_ */
|
@ -216,3 +216,8 @@ void writel(unsigned int value, void* address)
|
||||
volatile unsigned int* ptr = (volatile unsigned int*)address;
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
uint32_t readl(volatile uint32_t *addr)
|
||||
{
|
||||
return *addr;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define STRING_H_
|
||||
|
||||
#include "stddef.h"
|
||||
#include "stdint.h"
|
||||
|
||||
#define LBLOCKSIZE (sizeof(long))
|
||||
#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
|
||||
@ -26,6 +27,7 @@ char *strchr (const char *s, int c);
|
||||
char *strrchr (const char *s, int c);
|
||||
long atol (const char *s);
|
||||
void writel (unsigned int value, void* address);
|
||||
uint32_t readl(volatile uint32_t *addr);
|
||||
|
||||
// C-driven optimized functions
|
||||
void *memset (void *m, int c, size_t n);
|
||||
@ -37,6 +39,7 @@ void *memset (void *m, int c, size_t n);
|
||||
/* How many bytes are copied each iteration of the 4X unrolled loop. */
|
||||
#define BIGBLOCKSIZE (sizeof(long) << 2)
|
||||
|
||||
static void *__optimized_memcpy (void *dst0, const void *src0, size_t len0) __attribute__((unused));
|
||||
static void *__optimized_memcpy (void *dst0, const void *src0, size_t len0)
|
||||
{
|
||||
char *dst = dst0;
|
||||
@ -63,9 +66,9 @@ static void *__optimized_memcpy (void *dst0, const void *src0, size_t len0)
|
||||
len0 -= LBLOCKSIZE;
|
||||
}
|
||||
|
||||
/* Pick up any residual with a byte copier. */
|
||||
dst = (char*)aligned_dst;
|
||||
src = (char*)aligned_src;
|
||||
/* Pick up any residual with a byte copier. */
|
||||
dst = (char*)aligned_dst;
|
||||
src = (char*)aligned_src;
|
||||
}
|
||||
|
||||
while (len0--)
|
||||
|
Loading…
Reference in New Issue
Block a user