mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
smartcard: modify smartcard driver for 8.1
PD#168901: smartcard modify smartcard driver for 8.1 Change-Id: Ib0b81009e434d5f6c513bfc52bbfeef48414ef39 Signed-off-by: Yinming Ding <yinming.ding@amlogic.com>
This commit is contained in:
@@ -1263,6 +1263,39 @@
|
||||
&clkc CLKID_HIU_IFACE>;
|
||||
clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop";
|
||||
};
|
||||
|
||||
/* SMC */
|
||||
smartcard{
|
||||
compatible = "amlogic,smartcard";
|
||||
irq_trigger_type = "GPIO_IRQ_LOW";
|
||||
|
||||
reset_pin-gpios = <&gpio GPIODV_21 GPIO_ACTIVE_HIGH>;
|
||||
detect_pin-gpios = <&gpio GPIODV_20 GPIO_ACTIVE_HIGH>;
|
||||
enable_5v3v_pin-gpios = <&gpio GPIODV_19 GPIO_ACTIVE_HIGH>;
|
||||
enable_pin-gpios = <&gpio GPIODV_20 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
interrupts = <0 37 1>;
|
||||
interrupt-names = "smc0_irq";
|
||||
/*
|
||||
*Smc clock source, if change this,
|
||||
*you must adjust clk and divider in smartcard.c
|
||||
*/
|
||||
smc0_clock_source = <0>;
|
||||
smc0_irq = <37>; //smc irq
|
||||
/*0: high voltage on detect pin indicates card in.*/
|
||||
smc0_det_invert = <0>;
|
||||
smc0_5v3v_level = <0>;
|
||||
/*Ordinarily,smartcard controller needs a enable pin.*/
|
||||
smc_need_enable_pin = "no";
|
||||
reset_level = <0>;
|
||||
smc0_enable_level = <0>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sd_iso7816_pins>;
|
||||
clocks = <&clkc CLKID_SMART_CARD>;
|
||||
clock-names = "smartcard";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
&efuse {
|
||||
status = "ok";
|
||||
|
||||
@@ -825,6 +825,16 @@
|
||||
};
|
||||
};
|
||||
|
||||
sd_iso7816_pins:sd_iso7816_pins {
|
||||
mux {
|
||||
groups = "iso7816_clk_dv",
|
||||
"iso7816_data_dv";
|
||||
function = "iso7816";
|
||||
input-enable;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
nand_pulldown: nand_pulldown {
|
||||
mux {
|
||||
groups = "emmc_nand_d07",
|
||||
|
||||
@@ -405,8 +405,8 @@ static const unsigned int dvp_d2_9_pins[] = {
|
||||
};
|
||||
|
||||
/*iso7816*/
|
||||
static const unsigned int iso7816_clk_pins[] = { GPIOZ_6 };
|
||||
static const unsigned int iso7816_data_pins[] = { GPIOZ_7 };
|
||||
static const unsigned int iso7816_clk_dv_pins[] = { GPIODV_22 };
|
||||
static const unsigned int iso7816_data_dv_pins[] = { GPIODV_23 };
|
||||
|
||||
static struct meson_pmx_group meson_gxl_periphs_groups[] = {
|
||||
GPIO_GROUP(GPIOZ_0),
|
||||
@@ -588,7 +588,6 @@ static struct meson_pmx_group meson_gxl_periphs_groups[] = {
|
||||
GROUP(tsin_fail_b_z4, 3, 15), /*z4*/
|
||||
GROUP(dvp_d2_9, 3, 11), /*z4*/
|
||||
GROUP(i2sout_ch23_z5, 3, 26), /*z5*/
|
||||
GROUP(iso7816_clk, 4, 9), /*z6*/
|
||||
GROUP(i2sout_ch45_z6, 3, 25), /*z6*/
|
||||
GROUP(i2sout_ch67_z7, 3, 24), /*z7*/
|
||||
GROUP(spi_sclk_0, 4, 4), /*z11*/
|
||||
@@ -643,6 +642,8 @@ static struct meson_pmx_group meson_gxl_periphs_groups[] = {
|
||||
GROUP(i2c_scl_c_dv19, 1, 16), /*dv19*/
|
||||
GROUP(pwm_b, 2, 11), /*dv29*/
|
||||
GROUP(pwm_d, 2, 12), /*dv28*/
|
||||
GROUP(iso7816_clk_dv, 2, 18), /*dv22*/
|
||||
GROUP(iso7816_data_dv, 2, 17), /*dv23*/
|
||||
|
||||
/* Bank BOOT */
|
||||
GROUP(emmc_nand_d07, 7, 31),
|
||||
@@ -997,6 +998,11 @@ static const char *const dmic_groups[] = {
|
||||
"dmic_in_z8", "dmic_clk_z9",
|
||||
};
|
||||
|
||||
static const char * const iso7816_groups[] = {
|
||||
"iso7816_clk_dv", "iso7816_data_dv",
|
||||
};
|
||||
|
||||
|
||||
static struct meson_pmx_func meson_gxl_periphs_functions[] = {
|
||||
FUNCTION(gpio_periphs),
|
||||
FUNCTION(emmc),
|
||||
@@ -1004,6 +1010,7 @@ static struct meson_pmx_func meson_gxl_periphs_functions[] = {
|
||||
FUNCTION(uart_a),
|
||||
FUNCTION(uart_b),
|
||||
FUNCTION(uart_c),
|
||||
FUNCTION(iso7816),
|
||||
FUNCTION(eth),
|
||||
FUNCTION(jtag),
|
||||
FUNCTION(pwm_a),
|
||||
|
||||
@@ -19,22 +19,23 @@
|
||||
#define __MACH_MESON8_REG_ADDR_H_
|
||||
#include <linux/amlogic/iomap.h>
|
||||
#define CBUS_REG_ADDR(_r) aml_read_cbus(_r)
|
||||
#define SMARTCARD_REG0 0x2110
|
||||
#define SMARTCARD_REG_BASE smc_get_reg_base()
|
||||
#define SMARTCARD_REG0 (SMARTCARD_REG_BASE + 0x0)
|
||||
#define P_SMARTCARD_REG0 CBUS_REG_ADDR(SMARTCARD_REG0)
|
||||
#define SMARTCARD_REG1 0x2111
|
||||
#define SMARTCARD_REG1 (SMARTCARD_REG_BASE + 0x1)
|
||||
#define P_SMARTCARD_REG1 CBUS_REG_ADDR(SMARTCARD_REG1)
|
||||
#define SMARTCARD_REG2 0x2112
|
||||
#define SMARTCARD_REG2 (SMARTCARD_REG_BASE + 0x2)
|
||||
#define P_SMARTCARD_REG2 CBUS_REG_ADDR(SMARTCARD_REG2)
|
||||
#define SMARTCARD_STATUS 0x2113
|
||||
#define SMARTCARD_STATUS (SMARTCARD_REG_BASE + 0x3)
|
||||
#define P_SMARTCARD_STATUS CBUS_REG_ADDR(SMARTCARD_STATUS)
|
||||
#define SMARTCARD_INTR 0x2114
|
||||
#define SMARTCARD_INTR (SMARTCARD_REG_BASE + 0x4)
|
||||
#define P_SMARTCARD_INTR CBUS_REG_ADDR(SMARTCARD_INTR)
|
||||
#define SMARTCARD_REG5 0x2115
|
||||
#define SMARTCARD_REG5 (SMARTCARD_REG_BASE + 0x5)
|
||||
#define P_SMARTCARD_REG5 CBUS_REG_ADDR(SMARTCARD_REG5)
|
||||
#define SMARTCARD_REG6 0x2116
|
||||
#define SMARTCARD_REG6 (SMARTCARD_REG_BASE + 0x6)
|
||||
#define P_SMARTCARD_REG6 CBUS_REG_ADDR(SMARTCARD_REG6)
|
||||
#define SMARTCARD_FIFO 0x2117
|
||||
#define SMARTCARD_FIFO (SMARTCARD_REG_BASE + 0x7)
|
||||
#define P_SMARTCARD_FIFO CBUS_REG_ADDR(SMARTCARD_FIFO)
|
||||
#define SMARTCARD_REG8 0x2118
|
||||
#define SMARTCARD_REG8 (SMARTCARD_REG_BASE + 0x8)
|
||||
#define P_SMARTCARD_REG8 CBUS_REG_ADDR(SMARTCARD_REG8)
|
||||
#endif
|
||||
|
||||
@@ -156,10 +156,14 @@ while (0)
|
||||
static struct file *debug_filp;
|
||||
static loff_t debug_file_pos;
|
||||
static int smc_debug;
|
||||
#ifdef MEM_DEBUG
|
||||
static char *dbuf;
|
||||
static int dread, dwrite;
|
||||
static int dcnt;
|
||||
static struct reset_control *aml_smartcard_reset_ctrl;
|
||||
#endif
|
||||
/*no used reset ctl,need use clk in 4.9 kernel*/
|
||||
static struct clk *aml_smartcard_clk;
|
||||
|
||||
#define REG_READ 0
|
||||
#define REG_WRITE 1
|
||||
void operate_reg(unsigned int reg, int read_write, unsigned int *value)
|
||||
@@ -191,6 +195,8 @@ void debug_write(const char __user *buf, size_t count)
|
||||
|
||||
set_fs(old_fs);
|
||||
}
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
static void open_debug(void)
|
||||
{
|
||||
debug_filp = filp_open(DEBUG_FILE_NAME, O_WRONLY, 0);
|
||||
@@ -222,6 +228,7 @@ static size_t print_time(u64 ts, char *buf)
|
||||
return sprintf(buf, "[%5lu.%06lu] ",
|
||||
(unsigned long)ts, rem_nsec / 1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id smc_dt_match[] = {
|
||||
@@ -386,6 +393,7 @@ static struct mutex smc_lock;
|
||||
static int smc_major;
|
||||
static struct smc_dev smc_dev[SMC_DEV_COUNT];
|
||||
static int ENA_GPIO_PULL = 1;
|
||||
static int DIV_SMC = 3;
|
||||
|
||||
#ifdef SW_INVERT
|
||||
static const unsigned char inv_table[256] = {
|
||||
@@ -530,6 +538,30 @@ static ssize_t store_freq(struct class *class,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_div_smc(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "div -> %d\n", DIV_SMC);
|
||||
}
|
||||
|
||||
static ssize_t store_div_smc(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
int div = 0;
|
||||
|
||||
if (kstrtoint(buf, 0, &div))
|
||||
return -EINVAL;
|
||||
|
||||
if (div)
|
||||
DIV_SMC = div;
|
||||
|
||||
pr_dbg("div -> %d\n", DIV_SMC);
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
static ssize_t show_debug(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
@@ -598,6 +630,7 @@ static struct class_attribute smc_class_attrs[] = {
|
||||
__ATTR(smc_gpio_pull, 0644, show_gpio_pull, set_gpio_pull),
|
||||
__ATTR(ctrl_5v3v, 0644, show_5v3v, store_5v3v),
|
||||
__ATTR(freq, 0644, show_freq, store_freq),
|
||||
__ATTR(div_smc, 0644, show_div_smc, store_div_smc),
|
||||
#ifdef MEM_DEBUG
|
||||
__ATTR(debug, 0644, show_debug, store_debug),
|
||||
#endif
|
||||
@@ -609,76 +642,17 @@ static struct class smc_class = {
|
||||
.class_attrs = smc_class_attrs,
|
||||
};
|
||||
|
||||
static unsigned long get_clk(char *name)
|
||||
|
||||
|
||||
long smc_get_reg_base(void)
|
||||
{
|
||||
struct clk *clk = NULL;
|
||||
int newbase = 0;
|
||||
|
||||
clk = clk_get_sys(name, NULL);
|
||||
if (clk)
|
||||
return clk_get_rate(clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long get_module_clk(int sel)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_ARC700
|
||||
return get_mpeg_clk();
|
||||
#else
|
||||
|
||||
unsigned long clk = 0;
|
||||
#ifdef CONFIG_ARCH_MESON6/*M6*/
|
||||
/*sel = [0:clk81, 1:ddr-pll, 2:fclk-div5, 3:XTAL]*/
|
||||
switch (sel) {
|
||||
case 0:
|
||||
clk = get_clk("clk81");
|
||||
break;
|
||||
case 1:
|
||||
clk = get_clk("pll_ddr");
|
||||
break;
|
||||
case 2:
|
||||
clk = get_clk("fixed")/5;
|
||||
break;
|
||||
case 3:
|
||||
clk = get_clk("xtal");
|
||||
break;
|
||||
if (get_cpu_type() > MESON_CPU_MAJOR_ID_TXL &&
|
||||
get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX) {
|
||||
newbase = 1;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* sel = [0:fclk-div2/fclk-div4(M8 and further),
|
||||
* 1:fclk-div3, 2:fclk-div5, 3:XTAL]
|
||||
*/
|
||||
switch (sel) {
|
||||
#if defined(MESON_CPU_TYPE_MESON8) && (MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8)
|
||||
case 0:
|
||||
clk = get_clk("pll_fixed") / 4;
|
||||
break;
|
||||
#else/*M6TV/TVD/TVLITE*/
|
||||
case 0:
|
||||
clk = 1000000000;
|
||||
break;
|
||||
/*
|
||||
* case 0: clk = get_clk("fixed")/2;
|
||||
* break;
|
||||
*/
|
||||
#endif
|
||||
case 1:
|
||||
clk = get_clk("pll_fixed") / 3;
|
||||
break;
|
||||
case 2:
|
||||
clk = get_clk("pll_fixed") / 5;
|
||||
break;
|
||||
case 3:
|
||||
clk = get_clk("xtal");
|
||||
break;
|
||||
}
|
||||
#endif /*M6*/
|
||||
|
||||
if (!clk)
|
||||
pr_error("fail: unknown clk source");
|
||||
|
||||
return clk;
|
||||
|
||||
#endif
|
||||
return (newbase) ? 0x9400 : 0x2110;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_OF
|
||||
@@ -767,9 +741,7 @@ static int smc_hw_set_param(struct smc_dev *smc)
|
||||
* SMC_ANSWER_TO_RST *reg1;
|
||||
* SMC_INTERRUPT_Reg *reg_int;
|
||||
*/
|
||||
unsigned int sys_clk_rate = get_module_clk(clock_source);
|
||||
unsigned long freq_cpu =
|
||||
sys_clk_rate / 1000 * 22; /**10 adjust freq temporarily*/
|
||||
unsigned long freq_cpu = clk_get_rate(aml_smartcard_clk)/1000*DIV_SMC;
|
||||
|
||||
pr_error("hw set param\n");
|
||||
|
||||
@@ -813,6 +785,7 @@ static int smc_hw_set_param(struct smc_dev *smc)
|
||||
pr_error("xmit_par:%d\n", smc->param.xmit_parity);
|
||||
pr_error("xmit_rep:%d\n", smc->param.xmit_repeat_dis);
|
||||
pr_error("xmit_try:%d\n", smc->param.xmit_retries);
|
||||
pr_error("clk_tcnt:%d freq_cpu:%ld\n", reg2->clk_tcnt, freq_cpu);
|
||||
|
||||
v = SMC_READ_REG(REG5);
|
||||
reg5 = (struct SMCCARD_HW_Reg5 *)&v;
|
||||
@@ -870,10 +843,7 @@ static int smc_hw_setup(struct smc_dev *smc)
|
||||
struct SMCCARD_HW_Reg5 *reg5;
|
||||
struct SMCCARD_HW_Reg6 *reg6;
|
||||
|
||||
unsigned int sys_clk_rate = get_module_clk(clock_source);
|
||||
|
||||
unsigned long freq_cpu = sys_clk_rate
|
||||
/ 1000 * 22; /**10 adjust freq temporarily*/
|
||||
unsigned long freq_cpu = clk_get_rate(aml_smartcard_clk)/1000*DIV_SMC;
|
||||
|
||||
pr_error("SMC CLK SOURCE - %luKHz\n", freq_cpu);
|
||||
|
||||
@@ -938,6 +908,7 @@ static int smc_hw_setup(struct smc_dev *smc)
|
||||
pr_error("xmit_par:%d\n", smc->param.xmit_parity);
|
||||
pr_error("xmit_rep:%d\n", smc->param.xmit_repeat_dis);
|
||||
pr_error("xmit_try:%d\n", smc->param.xmit_retries);
|
||||
pr_error("clk_tcnt:%d freq_cpu:%ld\n", reg2->clk_tcnt, freq_cpu);
|
||||
|
||||
v = SMC_READ_REG(INTR);
|
||||
reg_int = (struct SMC_INTERRUPT_Reg *)&v;
|
||||
@@ -1088,7 +1059,7 @@ static int smc_hw_deactive(struct smc_dev *smc)
|
||||
} else {
|
||||
if (smc->use_enable_pin)
|
||||
_gpio_out(smc->enable_pin,
|
||||
!smc->enable_level,
|
||||
smc->enable_level,
|
||||
SMC_ENABLE_PIN_NAME);
|
||||
}
|
||||
if (ENA_GPIO_PULL > 0) {
|
||||
@@ -1800,7 +1771,7 @@ static void smc_dev_deinit(struct smc_dev *smc)
|
||||
}
|
||||
if (smc->use_enable_pin)
|
||||
_gpio_free(smc->enable_pin, SMC_ENABLE_PIN_NAME);
|
||||
reset_control_assert(aml_smartcard_reset_ctrl);
|
||||
clk_disable_unprepare(aml_smartcard_clk);
|
||||
#if 0
|
||||
if (smc->pin_clk_pin != -1)
|
||||
_gpio_free(smc->pin_clk_pin, SMC_CLK_PIN_NAME);
|
||||
@@ -1846,7 +1817,7 @@ static int _set_gpio(struct smc_dev *smc, struct gpio_desc **gpiod,
|
||||
} else if (input_output == INPUT) {
|
||||
*gpiod = gpiod_get(&smc->pdev->dev, str, GPIOD_IN);
|
||||
ret = gpiod_direction_input(*gpiod);
|
||||
//ret |= gpiod_set_pullup(*gpiod, 1);
|
||||
ret |= gpiod_set_pull(*gpiod, GPIOD_PULL_UP);
|
||||
} else
|
||||
pr_dbg("SMC Request gpio direction invalid\n");
|
||||
|
||||
@@ -1861,6 +1832,7 @@ static int smc_dev_init(struct smc_dev *smc, int id)
|
||||
u32 value;
|
||||
char buf[32];
|
||||
const char *dts_str;
|
||||
struct resource *res;
|
||||
#endif
|
||||
|
||||
#if defined(MESON_CPU_TYPE_MESON8) && (MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8)
|
||||
@@ -1910,7 +1882,7 @@ static int smc_dev_init(struct smc_dev *smc, int id)
|
||||
pr_error("%s: %d\n", buf, smc->enable_level);
|
||||
if (smc->enable_pin != NULL) {
|
||||
_gpio_out(smc->enable_pin,
|
||||
!smc->enable_level,
|
||||
smc->enable_level,
|
||||
SMC_ENABLE_PIN_NAME);
|
||||
pr_error("enable_pin: -->(%d)\n",
|
||||
(!smc->enable_level)?1:0);
|
||||
@@ -1953,7 +1925,7 @@ static int smc_dev_init(struct smc_dev *smc, int id)
|
||||
smc->irq_num = smc0_irq;
|
||||
if (smc->irq_num == -1) {
|
||||
snprintf(buf, sizeof(buf), "smc%d_irq", id);
|
||||
#ifdef CONFIG_OF
|
||||
#if 0
|
||||
ret = of_property_read_u32(smc->pdev->dev.of_node, buf, &value);
|
||||
if (!ret) {
|
||||
smc->irq_num = value;
|
||||
@@ -2183,7 +2155,7 @@ static int smc_dev_init(struct smc_dev *smc, int id)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
smc->enable_5v3v_level = 0;
|
||||
if (1) {
|
||||
snprintf(buf, sizeof(buf), "smc%d_5v3v_level", id);
|
||||
@@ -2192,7 +2164,7 @@ static int smc_dev_init(struct smc_dev *smc, int id)
|
||||
if (!ret) {
|
||||
smc->enable_5v3v_level = value;
|
||||
pr_error("%s: %d\n", buf, smc->enable_5v3v_level);
|
||||
if (smc->enable_5v3v_pin != -1) {
|
||||
if (smc->enable_5v3v_pin != NULL) {
|
||||
_gpio_out(smc->enable_5v3v_pin,
|
||||
smc->enable_5v3v_level,
|
||||
SMC_ENABLE_5V3V_PIN_NAME);
|
||||
@@ -2236,7 +2208,7 @@ static int smc_dev_init(struct smc_dev *smc, int id)
|
||||
#else
|
||||
smc->irq_num = request_irq(smc->irq_num,
|
||||
(irq_handler_t)smc_irq_handler,
|
||||
IRQF_SHARED, "smc", smc);
|
||||
IRQF_SHARED|IRQF_TRIGGER_RISING, "smc", smc);
|
||||
if (smc->irq_num < 0) {
|
||||
pr_error("request irq error!\n");
|
||||
smc_dev_deinit(smc);
|
||||
@@ -2586,9 +2558,13 @@ static int smc_probe(struct platform_device *pdev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
aml_smartcard_reset_ctrl =
|
||||
devm_reset_control_get(&pdev->dev, "smartcard");
|
||||
reset_control_deassert(aml_smartcard_reset_ctrl);
|
||||
aml_smartcard_clk =
|
||||
devm_clk_get(&pdev->dev, "smartcard");
|
||||
if (IS_ERR_OR_NULL(aml_smartcard_clk)) {
|
||||
dev_err(&pdev->dev, "get smartcard clk fail\n");
|
||||
return -1;
|
||||
}
|
||||
clk_prepare_enable(aml_smartcard_clk);
|
||||
if (smc) {
|
||||
smc->init = 1;
|
||||
smc->pdev = pdev;
|
||||
|
||||
@@ -22,4 +22,5 @@ extern int amlogic_gpio_direction_output(unsigned int pin, int value,
|
||||
const char *owner);
|
||||
extern int amlogic_gpio_request(unsigned int pin, const char *label);
|
||||
extern unsigned long get_mpeg_clk(void);
|
||||
extern long smc_get_reg_base(void);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user