blob: d0d5cc5a1e4c01c614ff4f80fb2442bc0d34191f [file] [log] [blame]
/*
* sound/soc/amlogic/auge/earc_hw.c
*
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/amlogic/media/sound/spdif_info.h>
#include "earc_hw.h"
void earcrx_pll_refresh(struct regmap *top_map)
{
/* pll tdc mode */
mmio_update_bits(top_map, EARCRX_PLL_CTRL3,
0x1 << 15, 0x1 << 15);
/* pll self reset */
mmio_update_bits(top_map, EARCRX_PLL_CTRL0,
0x1 << 29, 0x1 << 29);
mmio_update_bits(top_map, EARCRX_PLL_CTRL0,
0x1 << 29, 0x0 << 29);
mmio_update_bits(top_map, EARCRX_PLL_CTRL3,
0x1 << 15, 0x0 << 15);
}
void earcrx_cmdc_init(struct regmap *top_map)
{
/* set irq mask */
mmio_write(top_map, EARCRX_CMDC_INT_MASK,
(1 << 15) | /* idle2_int */
(1 << 14) | /* idle1_int */
(1 << 13) | /* disc2_int */
(1 << 12) | /* disc1_int */
(1 << 11) | /* earc_int */
(1 << 10) | /* hb_status_int */
(1 << 9) | /* losthb_int */
(1 << 8) | /* timeout_int */
(0 << 7) | /* status_ch_int */
(0 << 6) | /* int_rec_invalid_id */
(0 << 5) | /* int_rec_invalid_offset */
(0 << 4) | /* int_rec_unexp */
(0 << 3) | /* int_rec_ecc_err */
(0 << 2) | /* int_rec_parity_err */
(0 << 1) | /* int_recv_packet */
(0 << 0) /* int_rec_time_out */
);
mmio_write(top_map, EARCRX_ANA_CTRL0,
0x1 << 31 | /* earcrx_en_d2a */
0x10 << 24 | /* earcrx_cmdcrx_reftrim */
0x8 << 20 | /* earcrx_idr_trim */
0x10 << 15 | /* earcrx_rterm_trim */
0x4 << 12 | /* earcrx_cmdctx_ack_hystrim */
0x10 << 7 | /* earcrx_cmdctx_ack_reftrim */
0x1 << 4 | /* earcrx_cmdcrx_rcfilter_sel */
0x4 << 0 /* earcrx_cmdcrx_hystrim */
);
mmio_write(top_map, EARCRX_PLL_CTRL3,
0x2 << 20 | /* earcrx_pll_bias_adj */
0x4 << 16 | /* earcrx_pll_rou */
0x1 << 13 /* earcrx_pll_dco_sdm_e */
);
mmio_write(top_map, EARCRX_PLL_CTRL0,
0x1 << 28 | /* earcrx_pll_en */
0x1 << 23 | /* earcrx_pll_dmacrx_sqout_rstn_sel */
0x1 << 10 /* earcrx_pll_n */
);
}
void earcrx_cmdc_arc_connect(struct regmap *cmdc_map, bool init)
{
if (init)
mmio_update_bits(cmdc_map,
EARC_RX_CMDC_VSM_CTRL0,
0x7 << 25,
0x1 << 27 | /* arc_initiated */
0x0 << 26 | /* arc_terminated */
0x1 << 25 /* arc_enable */
);
else
mmio_update_bits(cmdc_map,
EARC_RX_CMDC_VSM_CTRL0,
0x7 << 25,
0x0 << 27 | /* arc_initiated */
0x1 << 26 | /* arc_terminated */
0x0 << 25 /* arc_enable */
);
}
void earcrx_cmdc_hpd_detect(struct regmap *cmdc_map, bool st)
{
if (st) {
mmio_update_bits(cmdc_map,
EARC_RX_CMDC_VSM_CTRL0,
0x1 << 19,
0x1 << 19 /* comma_cnt_rst */
);
mmio_update_bits(cmdc_map,
EARC_RX_CMDC_VSM_CTRL0,
0x1 << 19 | 0xff << 0,
0x0 << 19 | /* comma_cnt_rst */
0xa << 0
);
} else {
/* soft reset */
mmio_update_bits(cmdc_map,
EARC_RX_CMDC_TOP_CTRL1,
0xf << 0,
0xf << 0);
mmio_update_bits(cmdc_map,
EARC_RX_CMDC_TOP_CTRL1,
0xf << 0,
0x0 << 0);
}
}
void earcrx_dmac_init(struct regmap *top_map, struct regmap *dmac_map)
{
mmio_write(top_map, EARCRX_DMAC_INT_MASK,
(0x0 << 17) | /* earcrx_ana_rst c_new_format_set */
(0x0 << 16) | /* earcrx_ana_rst c_earcrx_div2_hold_set */
(0x0 << 15) | /* earcrx_err_correct c_bcherr_int_set */
(0x0 << 14) | /* earcrx_err_correct r_afifo_overflow_set */
(0x0 << 13) | /* earcrx_err_correct r_fifo_overflow_set */
(0x0 << 12) | /* earcrx_user_bit_check r_fifo_overflow */
(0x0 << 11) | /* earcrx_user_bit_check c_fifo_thd_pass */
(0x0 << 10) | /* earcrx_user_bit_check c_u_pk_lost_int_set */
(0x0 << 9) | /* arcrx_user_bit_check c_iu_pk_end */
(0x0 << 8) | /* arcrx_biphase_decode c_chst_mute_clr */
(0x1 << 7) | /* arcrx_biphase_decode c_find_papb */
(0x1 << 6) | /* arcrx_biphase_decode c_valid_change */
(0x1 << 5) | /* arcrx_biphase_decode c_find_nonpcm2pcm */
(0x1 << 4) | /* arcrx_biphase_decode c_pcpd_change */
(0x1 << 3) | /* arcrx_biphase_decode c_ch_status_change */
(0x1 << 2) | /* arcrx_biphase_decode sample_mod_change */
(0x1 << 1) | /* arcrx_biphase_decode r_parity_err */
(0x0 << 0) /* arcrx_dmac_sync afifo_overflow */
);
mmio_write(dmac_map, EARCRX_DMAC_SYNC_CTRL0,
(1 << 16) | /* reg_ana_buf_data_sel_en */
(3 << 12) | /* reg_ana_buf_data_sel */
(7 << 8) | /* reg_ana_clr_cnt */
(7 << 4) /* reg_ana_set_cnt */
);
mmio_write(dmac_map, EARCRX_DMAC_UBIT_CTRL0,
(47 << 16) | /* reg_fifo_thd */
(1 << 12) | /* reg_user_lr */
(29 << 0) /* reg_data_bit */
);
mmio_write(dmac_map, EARCRX_ANA_RST_CTRL0, 1 << 31);
}
void earcrx_arc_init(struct regmap *dmac_map)
{
unsigned int spdifin_clk = 500000000;
/* sysclk/rate/32(bit)/2(ch)/2(bmc) */
unsigned int counter_32k = (spdifin_clk / (32000 * 64));
unsigned int counter_44k = (spdifin_clk / (44100 * 64));
unsigned int counter_48k = (spdifin_clk / (48000 * 64));
unsigned int counter_88k = (spdifin_clk / (88200 * 64));
unsigned int counter_96k = (spdifin_clk / (96000 * 64));
unsigned int counter_176k = (spdifin_clk / (176400 * 64));
unsigned int counter_192k = (spdifin_clk / (192000 * 64));
unsigned int mode0_th = 3 * (counter_32k + counter_44k) >> 1;
unsigned int mode1_th = 3 * (counter_44k + counter_48k) >> 1;
unsigned int mode2_th = 3 * (counter_48k + counter_88k) >> 1;
unsigned int mode3_th = 3 * (counter_88k + counter_96k) >> 1;
unsigned int mode4_th = 3 * (counter_96k + counter_176k) >> 1;
unsigned int mode5_th = 3 * (counter_176k + counter_192k) >> 1;
unsigned int mode0_timer = counter_32k >> 1;
unsigned int mode1_timer = counter_44k >> 1;
unsigned int mode2_timer = counter_48k >> 1;
unsigned int mode3_timer = counter_88k >> 1;
unsigned int mode4_timer = counter_96k >> 1;
unsigned int mode5_timer = (counter_176k >> 1);
unsigned int mode6_timer = (counter_192k >> 1);
mmio_write(dmac_map,
EARCRX_SPDIFIN_SAMPLE_CTRL0,
0x0 << 28 | /* detect by max_width */
(spdifin_clk / 10000) << 0 /* base timer */
);
mmio_write(dmac_map,
EARCRX_SPDIFIN_SAMPLE_CTRL1,
mode0_th << 20 |
mode1_th << 10 |
mode2_th << 0);
mmio_write(dmac_map,
EARCRX_SPDIFIN_SAMPLE_CTRL2,
mode3_th << 20 |
mode4_th << 10 |
mode5_th << 0);
mmio_write(dmac_map,
EARCRX_SPDIFIN_SAMPLE_CTRL3,
(mode0_timer << 24) |
(mode1_timer << 16) |
(mode2_timer << 8) |
(mode3_timer << 0)
);
mmio_write(dmac_map,
EARCRX_SPDIFIN_SAMPLE_CTRL4,
(mode4_timer << 24) |
(mode5_timer << 16) |
(mode6_timer << 8)
);
mmio_write(dmac_map,
EARCRX_SPDIFIN_CTRL0,
0x1 << 31 | /* reg_work_en */
0x0 << 30 | /* reg_chnum_sel */
0x1 << 25 | /* reg_findpapb_en */
0x1 << 24 | /* nonpcm2pcm_th enable */
0xFFF << 12 | /* reg_nonpcm2pcm_th */
0x1 << 2 /* reg_check_parity */
);
mmio_write(dmac_map,
EARCRX_SPDIFIN_CTRL2,
(1 << 14) | /* reg_earc_auto */
(1 << 13) /* reg_earcin_papb_lr */
);
mmio_write(dmac_map,
EARCRX_SPDIFIN_CTRL3,
(0xEC37 << 16) | /* reg_earc_pa_value */
(0x5A5A << 0) /* reg_earc_pb_value */
);
}
enum cmdc_st earcrx_cmdc_get_state(struct regmap *cmdc_map)
{
int val = mmio_read(cmdc_map, EARC_RX_CMDC_STATUS0);
enum cmdc_st state = (enum cmdc_st)(val & 0x7);
return state;
}
enum attend_type earcrx_cmdc_get_attended_type(struct regmap *cmdc_map)
{
int val = mmio_read(cmdc_map, EARC_RX_CMDC_STATUS0);
enum cmdc_st state = (enum cmdc_st)(val & 0x7);
enum attend_type type = ATNDTYP_DISCNCT;
if ((val & (1 << 0x3)) && (state == CMDC_ST_ARC))
type = ATNDTYP_ARC;
else if ((val & (1 << 0x4)) && (state == CMDC_ST_EARC))
type = ATNDTYP_EARC;
return type;
}
void earcrx_cdmc_clr_irqs(struct regmap *top_map, int clr)
{
mmio_write(top_map, EARCRX_CMDC_INT_PENDING, clr);
}
int earcrx_cdmc_get_irqs(struct regmap *top_map)
{
return mmio_read(top_map, EARCRX_CMDC_INT_PENDING);
}
void earcrx_dmac_clr_irqs(struct regmap *top_map, int clr)
{
mmio_write(top_map, EARCRX_DMAC_INT_PENDING, clr);
}
int earcrx_dmac_get_irqs(struct regmap *top_map)
{
return mmio_read(top_map, EARCRX_DMAC_INT_PENDING);
}
void earcrx_enable(struct regmap *cmdc_map,
struct regmap *dmac_map, bool enable)
{
enum attend_type type = earcrx_cmdc_get_attended_type(cmdc_map);
if (enable) {
mmio_update_bits(dmac_map, EARCRX_DMAC_SYNC_CTRL0,
1 << 30, /* reg_rst_afifo_out_n */
1 << 30);
mmio_update_bits(dmac_map, EARCRX_DMAC_SYNC_CTRL0,
1 << 29, /* reg_rst_afifo_in_n */
0x1 << 29);
mmio_update_bits(dmac_map, EARCRX_ERR_CORRECT_CTRL0,
1 << 29, /* reg_rst_afifo_out_n */
1 << 29
);
mmio_update_bits(dmac_map, EARCRX_ERR_CORRECT_CTRL0,
1 << 28, /* reg_rst_afifo_in_n */
1 << 28 /* reg_rst_afifo_in_n */
);
} else {
mmio_update_bits(dmac_map, EARCRX_DMAC_SYNC_CTRL0,
0x3 << 29,
0x0 << 29);
mmio_update_bits(dmac_map, EARCRX_ERR_CORRECT_CTRL0,
0x3 << 28, 0x0 << 28);
}
if (type == ATNDTYP_EARC)
mmio_update_bits(dmac_map, EARCRX_DMAC_SYNC_CTRL0,
1 << 31, /* reg_work_en */
enable << 31);
else if (type == ATNDTYP_ARC) {
mmio_update_bits(dmac_map,
EARCRX_SPDIFIN_SAMPLE_CTRL0,
0x1 << 31, /* reg_work_enable */
enable << 31);
mmio_write(dmac_map, EARCRX_DMAC_SYNC_CTRL0, 0x0);
}
mmio_update_bits(dmac_map, EARCRX_DMAC_UBIT_CTRL0,
1 << 31, /* reg_work_enable */
enable << 31);
mmio_update_bits(dmac_map, EARCRX_ERR_CORRECT_CTRL0,
1 << 31,
enable << 31); /* reg_work_en */
mmio_update_bits(dmac_map, EARCRX_DMAC_TOP_CTRL0,
1 << 31,
enable << 31); /* reg_top_work_en */
}
void earctx_cmdc_int_mask(struct regmap *top_map)
{
mmio_write(top_map, EARCTX_CMDC_INT_MASK,
(0x0 << 17) | /* hpd_high_int */
(0x0 << 16) | /* hpd_low_int */
(0x1 << 15) | /* idle2_int */
(0x1 << 14) | /* idle1_int */
(0x1 << 13) | /* disc2_int */
(0x1 << 12) | /* disc1_int */
(0x1 << 11) | /* earc_int */
(0x0 << 10) | /* hb_status_int */
(0x1 << 9) | /* losthb_int */
(0x1 << 8) | /* timeout_int */
(0x0 << 7) | /* status_ch_int */
(0x0 << 6) | /* int_recv_finished */
(0x0 << 5) | /* int_recv_nack */
(0x0 << 4) | /* int_recv_norsp */
(0x0 << 3) | /* int_recv_unexp */
(0x0 << 2) | /* int_recv_data */
(0x0 << 1) | /* int_recv_ack */
(0x0 << 0) /* int_recv_ecc_err */
);
}
void earctx_cmdc_init(struct regmap *top_map)
{
/* ana */
mmio_write(top_map, EARCTX_ANA_CTRL0,
0x1 << 31 | /* earctx_en_d2a */
0x1 << 28 | /* earctx_cmdcrx_rcfilter_sel */
0x4 << 26 | /* earctx_cmdcrx_hystrim */
0x8 << 20 | /* earctx_idr_trim */
0x10 << 12 | /* earctx_rterm_trim */
0x4 << 8 | /* earctx_dmac_slew_con */
0x4 << 5 | /* earctx_cmdctx_ack_hystrim */
0x10 << 0 /* earctx_cmdctx_ack_reftrim */
);
}
void earctx_cmdc_arc_connect(struct regmap *cmdc_map, bool init)
{
if (init)
mmio_update_bits(cmdc_map,
EARC_TX_CMDC_VSM_CTRL0,
0x7 << 25,
0x1 << 27 | /* arc_initiated */
0x0 << 26 | /* arc_terminated */
0x1 << 25 /* arc_enable */
);
else
mmio_update_bits(cmdc_map,
EARC_TX_CMDC_VSM_CTRL0,
0x7 << 25,
0x0 << 27 | /* arc_initiated */
0x1 << 26 | /* arc_terminated */
0x0 << 25 /* arc_enable */
);
}
void earctx_cmdc_hpd_detect(struct regmap *top_map,
struct regmap *cmdc_map,
int earc_port, bool st)
{
/* select hdmirx_hpd */
mmio_update_bits(cmdc_map,
EARC_TX_CMDC_VSM_CTRL1,
0x1 << 8, /* cntl_hpd_sel */
0x1 << 8);
/* select hdmi_hpd mux */
mmio_update_bits(top_map, EARCTX_TOP_CTRL0,
0xf << 8,
0x1 << 11 | /* hdmi_hpd invent */
earc_port << 8 /* hdmi_hpd mux, port 0/1/2 */
);
if (st) {
mmio_update_bits(cmdc_map,
EARC_TX_CMDC_VSM_CTRL0,
0x1 << 19,
0x1 << 19 /* comma_cnt_rst */
);
mmio_update_bits(cmdc_map,
EARC_TX_CMDC_VSM_CTRL0,
0x1 << 19 | 0xf << 20,
0x0 << 19 | /* comma_cnt_rst */
0x3 << 20 | 0x3 << 22
);
mmio_update_bits(cmdc_map,
EARC_TX_CMDC_VSM_CTRL1,
0xff << 0,
0x4 << 0 /* comma_cnt_th */
);
} else {
/* soft reset */
mmio_update_bits(cmdc_map,
EARC_TX_CMDC_TOP_CTRL1,
0xf << 0,
0xf << 0);
mmio_update_bits(cmdc_map,
EARC_TX_CMDC_TOP_CTRL1,
0xf << 0,
0x0 << 0);
}
}
void earctx_dmac_init(struct regmap *top_map, struct regmap *dmac_map)
{
mmio_update_bits(dmac_map, EARCTX_SPDIFOUT_CTRL0,
0x3 << 28,
0x0 << 28);
mmio_update_bits(dmac_map, EARCTX_SPDIFOUT_CTRL0,
0x1 << 29, /* afifo out reset */
0x1 << 29);
mmio_update_bits(dmac_map, EARCTX_SPDIFOUT_CTRL0,
0x1 << 28 | /* afifo in reset */
0x1 << 26 | /* user Bit select */
0x1 << 24 | /* chdata select*/
0x1 << 20 | /* reg_data_sel, 1: data from 27bit */
0x1 << 19 | /* 0: lsb first */
0x1 << 18 | /* biphase encode valid Bit value sel */
0xff << 4, /* lane mask */
0x1 << 28 |
0x1 << 26 |
0x1 << 24 |
0x1 << 20 |
0x0 << 19 |
0x1 << 18 |
0x3 << 4 // ODO: lane 0 now
);
mmio_update_bits(dmac_map, EARCTX_ERR_CORRT_CTRL0,
0x1 << 16 | /* reg_ubit_fifo_init_n */
0x7 << 8 | /* r channel select */
0x7 << 4, /* l channel select */
0x1 << 16 |
0x1 << 8 |
0x0 << 4);
mmio_update_bits(dmac_map, EARCTX_ERR_CORRT_CTRL4,
0xf << 17,
0x1 << 19 | /* userBit sel, 1: reg_value */
0x1 << 18 | /* validBit sel, 1: reg_value */
0x1 << 17 /* reg_chst_sel, 1: reg_value */
);
}
void earctx_dmac_set_format(struct regmap *dmac_map,
int frddr_idx, int msb, int frddr_type)
{
mmio_update_bits(dmac_map, EARCTX_SPDIFOUT_CTRL1,
0x7 << 24 | /* frddr src */
0xff << 16 | /* waiting count after enabled */
0x1f << 8 | /* msb position */
0x7 << 4, /* frddr type */
frddr_idx << 24 |
0x40 << 16 |
msb << 8 |
frddr_type << 4);
mmio_update_bits(dmac_map, EARCTX_ERR_CORRT_CTRL4,
0x1f << 25,
0x1f << 25 /* msb */
);
/* for raw data */
mmio_update_bits(dmac_map, EARCTX_ERR_CORRT_CTRL3,
0x1f << 24,
0x17 << 24
);
}
void earctx_set_channel_status_info(struct regmap *dmac_map,
struct iec958_chsts *chsts)
{
/* ch status = reg_chsts0~B */
/* L Channel */
mmio_write(dmac_map, EARCTX_SPDIFOUT_CHSTS0,
((chsts->chstat1_l >> 8) & 0xf) << 24 | chsts->chstat0_l);
/* R Channel */
mmio_write(dmac_map, EARCTX_SPDIFOUT_CHSTS6,
((chsts->chstat1_r >> 8) & 0xf) << 24 | chsts->chstat0_r);
}
enum cmdc_st earctx_cmdc_get_state(struct regmap *cmdc_map)
{
int val = mmio_read(cmdc_map, EARC_TX_CMDC_STATUS0);
enum cmdc_st state = (enum cmdc_st)(val & 0x7);
return state;
}
enum attend_type earctx_cmdc_get_attended_type(struct regmap *cmdc_map)
{
int val = mmio_read(cmdc_map, EARC_TX_CMDC_STATUS0);
enum cmdc_st state = (enum cmdc_st)(val & 0x7);
enum attend_type tx_type = ATNDTYP_DISCNCT;
if ((val & (1 << 0x3)) && (state == CMDC_ST_ARC))
tx_type = ATNDTYP_ARC;
else if ((val & (1 << 0x4)) && (state == CMDC_ST_EARC))
tx_type = ATNDTYP_EARC;
return tx_type;
}
void earctx_cdmc_clr_irqs(struct regmap *top_map, int clr)
{
mmio_write(top_map, EARCTX_CMDC_INT_PENDING, clr);
}
int earctx_cdmc_get_irqs(struct regmap *top_map)
{
return mmio_read(top_map, EARCTX_CMDC_INT_PENDING);
}
void earctx_dmac_clr_irqs(struct regmap *top_map, int clr)
{
mmio_write(top_map, EARCTX_DMAC_INT_PENDING, clr);
}
int earctx_dmac_get_irqs(struct regmap *top_map)
{
return mmio_read(top_map, EARCTX_DMAC_INT_PENDING);
}
void earctx_enable(struct regmap *top_map,
struct regmap *cmdc_map,
struct regmap *dmac_map,
bool enable)
{
mmio_update_bits(dmac_map, EARCTX_SPDIFOUT_CTRL0,
0x1 << 31,
enable << 31);
mmio_update_bits(dmac_map, EARC_RX_CMDC_BIPHASE_CTRL1,
0x1 << 30,
enable << 30);
if (enable)
mmio_write(top_map, EARCTX_DMAC_INT_MASK,
(0x1 << 4) | /* fe_modulation c_hold_clr */
(0x1 << 3) | /* fe_modulation c_hold_start */
(0x1 << 2) | /* err_correct c_fifo_thd_less_pass */
(0x1 << 1) | /* err_correct r_fifo_overflow_set */
(0x1 << 0) /* err_correct c_fifo_empty_set */
);
else
mmio_write(top_map, EARCTX_DMAC_INT_MASK,
0x0
);
if (earctx_cmdc_get_attended_type(cmdc_map) == ATNDTYP_EARC) {
if (spdifout_is_raw()) {
mmio_update_bits(dmac_map, EARCTX_ERR_CORRT_CTRL3,
0x1 << 29,
enable << 29);
}
mmio_update_bits(dmac_map, EARCTX_FE_CTRL0,
0x1 << 30,
enable << 30);
}
}
static void earcrx_cmdc_get_reg(struct regmap *cmdc_map, int dev_id, int offset,
u8 *data, int bytes)
{
int i;
mmio_update_bits(cmdc_map, EARC_RX_CMDC_DEVICE_ID_CTRL,
0x1 << 31 | /* apb_write */
0x1 << 30 | /* apb_read */
0x1 << 29 | /* apb_w_r_done */
0xff << 8 | /* apb_rwid */
0xff << 0, /* apbrw_start_addr */
0x0 << 31 |
0x1 << 30 |
0x0 << 29 |
dev_id << 8 |
offset << 0);
for (i = 0; i < bytes; i++) {
data[i] = mmio_read(cmdc_map, EARC_RX_CMDC_DEVICE_RDATA);
pr_info("%s, data[%d]:%#x\n", __func__, i, data[i]);
}
mmio_update_bits(cmdc_map, EARC_RX_CMDC_DEVICE_ID_CTRL,
0x1 << 29, 0x1 << 29);
mmio_update_bits(cmdc_map, EARC_RX_CMDC_DEVICE_ID_CTRL,
0x1 << 29, 0x0 << 29);
}
static void earcrx_cmdc_set_reg(struct regmap *cmdc_map, int dev_id, int offset,
u8 *data, int bytes)
{
int i;
mmio_update_bits(cmdc_map, EARC_RX_CMDC_DEVICE_ID_CTRL,
0x1 << 31 | /* apb_write */
0x1 << 30 | /* apb_read */
0x1 << 29 | /* apb_w_r_done */
0xff << 8 | /* apb_rwid */
0xff << 0, /* apbrw_start_addr */
0x1 << 31 |
0x0 << 30 |
0x0 << 29 |
dev_id << 8 |
offset << 0);
for (i = 0; i < bytes; i++) {
pr_info("%s, data[%d]:%#x\n", __func__, i, data[i]);
mmio_write(cmdc_map, EARC_RX_CMDC_DEVICE_WDATA, data[i]);
}
mmio_update_bits(cmdc_map, EARC_RX_CMDC_DEVICE_ID_CTRL,
0x1 << 29, 0x1 << 29);
mmio_update_bits(cmdc_map, EARC_RX_CMDC_DEVICE_ID_CTRL,
0x1 << 29, 0x0 << 29);
}
/* Latency */
void earcrx_cmdc_get_latency(struct regmap *cmdc_map, u8 *latency)
{
earcrx_cmdc_get_reg(cmdc_map,
STAT_CTRL_DEV_ID,
ERX_LATENCY_REG,
latency,
1);
}
void earcrx_cmdc_set_latency(struct regmap *cmdc_map, u8 *latency)
{
earcrx_cmdc_set_reg(cmdc_map,
STAT_CTRL_DEV_ID,
ERX_LATENCY_REG,
latency,
1);
}
void earcrx_cmdc_get_cds(struct regmap *cmdc_map, u8 *cds)
{
earcrx_cmdc_get_reg(cmdc_map,
CAP_DEV_ID,
0x0,
cds,
CDS_MAX_BYTES);
}
void earcrx_cmdc_set_cds(struct regmap *cmdc_map, u8 *cds)
{
earcrx_cmdc_set_reg(cmdc_map,
CAP_DEV_ID,
0x0,
cds,
CDS_MAX_BYTES);
}
static int earctx_cmdc_get_reg(struct regmap *cmdc_map, int dev_id, int offset,
u8 *data, int bytes)
{
int val = 0, i;
int ret = -1;
mmio_update_bits(cmdc_map, EARC_TX_CMDC_MASTER_CTRL,
0x1 << 31 | /* master_cmd_rw, read */
0x1 << 30 | /* master_hb_ignore */
0xf << 24 | /* hb_cmd_val_th */
0xff << 16 | /* master_cmd_count */
0xff << 8 | /* master_cmd_id */
0xff << 0, /* master_cmd_address */
0x0 << 31 |
0x1 << 30 |
0x4 << 24 |
(bytes - 1) << 16 |
dev_id << 8 |
offset << 0);
/* wait read from rx done */
while (!(val & (1 << 29))) {
usleep_range(500, 1500);
val = mmio_read(cmdc_map, EARC_TX_CMDC_MASTER_CTRL);
}
mmio_update_bits(cmdc_map, EARC_TX_CMDC_DEVICE_ID_CTRL,
0x1 << 31 | /* apb_write */
0x1 << 30 | /* apb_read */
0x1 << 29 | /* apb_rw_done */
0x1 << 16 | /* hpb_rst_enable */
0xff << 8 | /* apb_rwid */
0xff << 0, /* apbrw_start_addr */
0x0 << 31 |
0x1 << 30 |
0x0 << 29 |
0x1 << 16 |
dev_id << 8 |
offset << 0);
for (i = 0; i < bytes; i++) {
data[i] = mmio_read(cmdc_map, EARC_TX_CMDC_DEVICE_RDATA);
pr_info("%s, bytes:%d, data[%d]:%#x\n",
__func__,
bytes,
i,
data[i]);
}
mmio_update_bits(cmdc_map, EARC_TX_CMDC_DEVICE_ID_CTRL,
0x1 << 29, 0x1 << 29);
mmio_update_bits(cmdc_map, EARC_TX_CMDC_DEVICE_ID_CTRL,
0x1 << 29, 0x0 << 29);
if (val & (1 << 29))
ret = 0;
return ret;
}
static int earctx_cmdc_set_reg(struct regmap *cmdc_map, int dev_id, int offset,
u8 *data, int bytes)
{
int val = 0, i;
int ret = -1;
int cnt = 0;
mmio_update_bits(cmdc_map, EARC_TX_CMDC_DEVICE_ID_CTRL,
0x1 << 31 | /* apb_write */
0x1 << 30 | /* apb_read */
0x1 << 29 | /* apb_rw_done */
0x1 << 16 | /* hpb_rst_enable */
0xff << 8 | /* apb_rwid */
0xff << 0, /* apbrw_start_addr */
0x1 << 31 |
0x0 << 30 |
0x0 << 29 |
0x1 << 16 |
dev_id << 8 |
offset << 0);
for (i = 0; i < bytes; i++) {
mmio_update_bits(cmdc_map, EARC_TX_CMDC_DEVICE_WDATA,
0xff << 0,
data[i] << 0);
pr_info("%s, data[%d]:%#x, bytes:%d\n",
__func__,
i,
data[i],
bytes);
}
mmio_update_bits(cmdc_map, EARC_TX_CMDC_MASTER_CTRL,
0x1 << 31 | /* master_cmd_rw, write */
0x1 << 30 | /* master_hb_ignore */
0xf << 24 | /* hb_cmd_cal_th */
0xff << 16 | /* master_cmd_count */
0xff << 8 | /* master_cmd_id */
0xff << 0, /* master_cmd_address */
0x1 << 31 |
0x1 << 30 |
4 << 24 |
(bytes - 1) << 16 |
dev_id << 8 |
offset << 0);
/* wait write done */
while (!(val & (1 << 29))) {
usleep_range(500, 1500);
val = mmio_read(cmdc_map, EARC_TX_CMDC_MASTER_CTRL);
cnt++;
}
pr_info("%s, cnt:%d\n", __func__, cnt);
mmio_update_bits(cmdc_map, EARC_TX_CMDC_DEVICE_ID_CTRL,
0x1 << 29, 0x1 << 29);
mmio_update_bits(cmdc_map, EARC_TX_CMDC_DEVICE_ID_CTRL,
0x1 << 29, 0x0 << 29);
if (val & (1 << 29))
ret = 0;
return ret;
}
/* Latency */
void earctx_cmdc_get_latency(struct regmap *cmdc_map, u8 *latency)
{
earctx_cmdc_get_reg(cmdc_map,
STAT_CTRL_DEV_ID,
ERX_LATENCY_REG,
latency,
1);
}
void earctx_cmdc_set_latency(struct regmap *cmdc_map, u8 *latency)
{
earctx_cmdc_set_reg(cmdc_map,
STAT_CTRL_DEV_ID,
ERX_LATENCY_REQ_REG,
latency,
1);
}
/* Capability Data Structure, fetch CDS from RX */
void earctx_cmdc_get_cds(struct regmap *cmdc_map, u8 *cds)
{
earctx_cmdc_get_reg(cmdc_map,
CAP_DEV_ID,
0x0,
cds,
CDS_MAX_BYTES);
}